diff options
author | Tor Norbye <tnorbye@google.com> | 2013-09-27 10:19:19 -0700 |
---|---|---|
committer | Tor Norbye <tnorbye@google.com> | 2013-09-27 10:19:28 -0700 |
commit | f7998d05c40c24ae66d1972abfcb070552b1d7b5 (patch) | |
tree | b0b97491f6e6591e53ea6a8f6c3a79a7dc685771 /java/java-psi-impl/src/com/intellij/psi | |
parent | beca9839b2866f90da9dc517c29df2ec25a6f6a8 (diff) | |
download | idea-f7998d05c40c24ae66d1972abfcb070552b1d7b5.tar.gz |
Snapshot cd724ea5e27634f1c84f893f10b646937a677d56 from idea/132.425 of git://git.jetbrains.org/idea/community.git
cd724ea: Code cleanup - Idea's warnings fixed - message moved to .properties file
c84855b: for performance use processNames api for java symbol contributor
334c509: IDEA-114064 Create "From Maven" library dialog doesn't handle full coords correctly (as advertised)
4e10a17: IDEA-109943 Download Library from Maven Repository: artifacts from repository with provider != maven2 are suggested, but repository is filtered off
d4bc48d: IDEA-114037 Code completion should prefer variable names to unimported class names
b7e5e6c: refix RUBY-11716: do not play with fire, always save and load in UTF-8 !
bb7ed8a: cleanup
15bd24e: cleanup
e56b270: ProjectId, don't add project level provider if project is not mapped
a0fb6a5: let IsNullCheck mean null->true, the former !null->false meaning was useless
26402542: test data fixed
f800733: new inference: input/output inference variables
56d872d: NPE: find usage for db element
3ffd6a0: IDEA-114003 XDebuger breakpoint properties: strage selection jumps in breakpoint tree
bbdef54: IDEA-114001 XDebuger Breakpoint Properties: enable in tree is not saved IDEA-114002 XDebuger breakpoint properties: don't close the dialog by double click IDEA-114004 XDebugger breakpoint properties: checkboxes synchronization is broken
f6ff871: IDEA-114001 XDebuger Breakpoint Properties: enable in tree is not saved IDEA-114002 XDebuger breakpoint properties: don't close the dialog by double click IDEA-114004 XDebugger breakpoint properties: checkboxes synchronization is broken
8f3d962: IDEABKL-6897 Enter inserts closing brace in wrong place
6a78643: IDEABKL-6897 Enter inserts closing brace in wrong place
06b899c: IDEA-114001 XDebuger Breakpoint Properties: enable in tree is not saved IDEA-114002 XDebuger breakpoint properties: don't close the dialog by double click IDEA-114004 XDebugger breakpoint properties: checkboxes synchronization is broken
aeda985: don't give focus to ant messages view
f525708: new inference: overload resolution for SAM return type for implicit lambda should be ignored
6692602: cleanup current file from highlighting markup
27c6645: compilation fix
1936bb2: IDEA-107453 Compilation error if overriding methods have different access modifiers
0ddcc36: api
a7f05e1: card layout fixed
b007608: IDEA-110203 IDEA ignores space after comma setting for methods declaration/call [CR-IC-2022]
ae02c17: hiding artifacts
90e6ed2: back to AddModuleWizard
4a029e9: Groovy: Pull-up members
6f9e810: NPE
fc48bab: pull-up
cbf7531: prepare pull-up refactoring for Groovy
6762d5f: cleanup
b26ffb2: spaces around inner classes
41e8e70: IDEA-113333 Java formatter breaks source code: Merges statements into line comments [CR-IC-2245]
ea91b55: IDEA-113815 keep "simple methods in one line" does not keep long methods [CR-IC-2486]
ecd65ad: Import Eclipse code style settings from XML profile (a part of IDEA-104068) [CR-IC-2219]
aacf1e4: IDEA-113844 (handling of core component initialization failures when spoiled by plugins)
8dc3ede: IDEA-112387 Reformat code with rearrange entires on = fail on enum [CR-IC-2205]
72ddb9e: Merge remote-tracking branch 'origin/master'
209340b: Add the description for MavenDuplicatePluginInspection.
de367e1: Merge branch 'svn1_8_new'
1a70497: IdeaTestAssistant: fix test data
d6a2510: svn: Fixed "Import" when path/url contains '@' symbol
94c4223: svn: Implemented "Export" action for command line
8913712: parameter popup: escape for annotation methods (IDEA-113971)
fdf7312: svn: Made event handler for checkout/export utilize passed progress indicator (instead of just current thread progress indicator)
f653713: IDEA-105758: Contradiction between error and fix actions (Java EE artifact)
eac456f: Platform: ability to provide native icons for PsiElements (PsiFile/Directory) AppCode: blue icons for folders
4d5c47a: IDEA-77519: Project fails to open when workspace.xml is empty
c40e732: two classes temporary restored to fix backward compatibility
b6b3bc6: added optional dependencies for framework support providers
a9dae78: IDEA-90661: recognize IBM JDK jars
6b44958: cleanup & javadoc
0c0a6a6: IDEA-108785 Allow applying the same context to many selected live templates
247661b: don't search for unknown path macros in the middle of xml unless asked so by PathMacroFilter (IDEA-102674)
90222d5: hopefully fix control flow building stack inconsistency assertions in case when a PCE is thrown
241e44b: EA-50288 - CCE: RefJavaUtilImpl.getTopLevelClass
22d5c2f: ensure to filter already inserted annotations (IDEA-113785)
27b76b4: inplace introducer: another case to restore expression (IDEA-113352)
603e138: add mnemonics (IDEA-113889)
a8c374c: XSuspendPolicyPanel "Make default" (requires for new JavaBreakpointType) remove unused methods
4f19472: CR-IC-2485 (deprecation policy specified; deprecated API usage upgraded)
7231807: JavaBreakpointType isSuspendThreadSupported true
8637e89: register JavaBreakpointType, but hide under system property java.debugger.xBreakpoint
0b2d5f0: cleanup
5cc1f5e: EA-50289 (CCE: TooBroadScopeInspection$TooBroadScopeInspectionFix.getCommentText)
505b86e: new inference: pertinent to applicability
8ac21fd: cleanup
2c5f39e: cleanup
f6efaa9: simplify DebuggerInvocationUtil
bf8865f: overrides
0d49e5b: JavaBreakpointType canPutAt
33ebea3: extract XLineBreakpointTypeBase
de7d963: extract XDebuggerEditorsProviderBase, init JavaBreakpointType (is not registered, so, not in action now)
ed777e6: remove deprecated canPutAt
9163435: overrides
44af67f8: extract XDebuggerUtil.getInstance().getGroupingByFileRuleAsList()
b93b27c: add missing Overrides
0857036: cleanup
ae791a7: new inference: test preparations
48120ab: IdeaTestAssistant: add resolving and completion inside TestDataPath annotation
971544b: remove empty unused class
c5642d9: hippie completion: split complex tokens by spaces
e1383b1: refix and add test for IDEA-90294 Don't use substring match in word completion
fbae94c: EA-49809 Made client factories final in SvnVcs
2b4b70f: Fix OC-8127: Appcode hangs on reformatting (endless right shift) +review CR-OC @Anton.Makeev, @Rustam.Vishnyakov
b7314cf: fix pycharm detection
5f0bb3c: revert error checking
5f99590: svn: Implemented "Import" action for command line
ad04905: svn: Changed import logic to use common commit event handler (instead of checkout event handler)
1a45be0: custom options
8d278a3: MavenArchetypesPanel extracted
32eeb4c: aggregation panel invisible
9388cc4: new project wizard: project type sorting
2c02a07: svn: Add "Skipped" event processing in commit/import output for command line
d365580: svn: Refactored commit output parsing for command line
b1cc312: immutable dfa offset stack
5c494fb: toolbarIcon is nullable
4304880: dfa: traverse only flushable variables, not all
ed08eab: immutable EqClass
03de519: overrides
f8661d9: return empty collection if list of storage files is empty
81a998c: IDEA-111030: Add Framework Support: Ok is disabled for the only selected Web Application
4ce1cc8: unused class removed
84f7401: svn: Added final status bar message for Import ("Committed revision xxx")
aa1d479: library editor: 'attach javadoc' extracted to separate button so the main '+' button won't show popup
1612198: cleanup
e180456: cleanup
546fffe: Merge remote-tracking branch 'origin/master'
c3caf6c: Merge remote-tracking branch 'origin/master'
5cd2b37: assertion for EA-45385 - NPE: XmlTagImpl.getDescriptor
99563ea: EA-49418 - NPE: InjectLanguageAction.invokeImpl
dc82859: cleanup
f70ef96: EA-50139 - assert: TextRange.<init>
990e410: svn: Removed unused code (from "Ignore" functionality)
6604613: svn: Implemented "Ignore" functionality on subversion level
d544d03: cleanup after notnullification
5330d9e: plugin suggester: suggest plugins from repository by unknown facet
1ccf92a: error which should never happen replaced by assertion
889d3ce: improved dialog for choosing root types of added roots
0eb34fa: hide "use out of process build" option from UI
d79e13e: plugin suggester: suggest plugins from repository by unknown facet
00a127b: Use shell options only if applicable.
b4f21b9: Don't fail to create SSH terminal session if we failed to create local terminal session.
8e5cb57: test for "Unnecessary unicode escape sequence" inspection
dc8acce: temp revert
c7c4431: fix SliceBackwardTest
3e16a04: svn: Implemented "Edit Revision Comment" action for command line
c54948a: 'async' added
e4f7950: svn: Correctly create externals that have '@' in url - add '@' at url end
9b66e1c: svn: Fix line separators duplication for "Create External" action for SVNKit
a98dc14: svn: Implemented "Create External" action for command line
32e30d1: EA-50206 - assert: FileManagerImpl.findFile
4a4c0cc: svn: Unify line separator for multiline properties
4b9422b: Reverted: Semantic highlighting level to avoid conflicts with "unused symbol" annotations [CR-IC-2435]
ad970ef: lambda: propagate wildcards elimination
e78ab51: lambda: check formal params for equality, eliminate wildcards during inference according to 15.27.3
fc9a196: new inference: ignore proper types in mutual eq constraints generation
7bc0048: new inference: void compatible according to return values
939fc45: prepare for test new inference
eef6eb2: new inference: exact method reference
172daec: new inference: eliminate delayed constrains according to 0.6.3
ec93384: postpone type evaluation
e689d68: new inference: make use of ex constraint
7838f8e: Merge branch 'safe-sudo-escaping'
1c22df9: Add grails-app/resources as resources folder, not a source folder.
a7f094d: fix NPE
e1fe819: Added ExecUtil.sudoAndGetOutput() with safe escaping and quoting for Mac and Linux
6bf3a02: fixed EA-48905 - SIOOBE: ParameterInfoComponent$OneLineComponent.buildLabelText
c853c69: system dependent paths in groovy shell
db7d97f: Merge remote-tracking branch 'origin/master'
65426f9: mark as DumbAware
0d1a074: Support active links in GotIt panel
c7297a0: debugging blinking test
755c6b2: IDEA-113938 "Submit feedback" should pre-fill project and affected version
ff45141: dfa: don't go into the same instruction twice with the same state
3361944: a bit more parsimonous DfaMemoryStateImpl.createCopy
028d28b: dfa states should not change while in queue => no need to copy them
1709382: dfa: use UnorderedPair instead of two-element set
e8dbc21: immutable DfaVariableState, for faster copying and less memory usage
666ed52: IDEA-70241 (Replace with '{@code}' inspection doesn't replace all occurrences in file.)
71bd9cf: Merge remote-tracking branch 'origin/master'
c923098: EA-47881 - IOE: GroovyPsiElementFactoryImpl.createGroovyFileChecked
8b97940: cleanup logging
6e4b81e: EA-50137 - assert: TestObject.addClassesListToJavaParameters
5381d51: cleanup
dc2d1b2: notnull
f419fab: "todo" moved out of lang-impl
97cd633: attributes cleanup
75b3eaa: notnull
c7fa9af: cleanup
f5b5bf4: cleanup
776b16b: cleanup
bf3cea4: made fields final
87913f7: cleanup
798e94e: cleanup, get rid of buggy duplicate node renderer
50f13e4: removed deprecated methods from ExternalAnnotator
6d9c887: avoid deprecated methods
4852116: minor
9cd549c: now Searchable. fixes test.
302302a: typo
26d8885: - handle strings with more than one quote used for start / end delimiters - proper retrieving syntax highlighter in case of non languge based syntaxhighlighter (quite often it is bound to file type) - Find: String literals only: Throwable at StringSearcher.scan() on XML with a string (IDEA-113885) - fix for backward search not ending when whole word option used
4dfd0c7: Encapsulate field dialog: explicit value for "Use accessors when field is accessible" when "as is" visibility is selected
e1aff45: typo :(((
6237b9b: test fixed
6c0d31b: test fixed
493cfae: update test data
711bca1: update test data
f1bc615: update test data
8dd18de: update test data
e61a901: update test data
0be96e9: update test data
aac178b: dfa: remove queued state duplication
6a25f5d: dfa: don't reschedule already processed states, cleanup
7559dfc: Semantic highlighting level to avoid conflicts with "unused symbol" annotations [CR-IC-2435], for WI-19396, WI-20126 (cherry picked from commit 56d66dc)
7c27aef: extract collectUsedJars() function
12f59ff: update test data
03df890: update test data
1efd604: update test data
2c1726e: update test data
24bf1d1: Merge remote-tracking branch 'origin/master'
8f26a8b: improved duplicates search in python extract method
9bfcbbe: setup resource roots when project is imported from Maven (IDEA-57398)
64594cd: diagnostics for EA-49831
0d76c32: add support for frameworks step: sorting restored
b510334: IDEA-113294 indentation of brace in a lambda expression corrected [CR-IC-2426]
9651be4: IDEA-113910 Gradle: code insight; dependencies DSL resolving
25595c8: new inference: checked exceptions compatibility constraint
6b8f295: dump highlighting test data without markup
636719b: now that we have dfa state hashing, use it instead of linear lookup
3813120: dfa: don't merge states when there's only one
3fd9ba8: IDEA-113910 Gradle: code insight; dependencies DSL resolving
57a6aeb: IDEA-113910 Gradle: code insight; dependencies resolving
da23b6c: Merge remote-tracking branch 'origin/master'
7ca6ea3: Merge remote branch 'origin/master'
cdc6d6a: show deprecated make implementation warning once on first compilation after project opening
090c4e3: dfa state merging: cache copies
e6ee024: Allows getting Gradle home without having a Project.
0391639: Gradle VM Options are now saved in between sessions.
f5412f0: resource root: show 'New Directory' action instead of 'New Package' under resource roots
1637f6b: notnullification
87f394f: IDEA-113904 (Add New Module from Project Structure dialog wants to create new project)
a7c75f6: IDEA-113865 ('Equals should check class of parameter' shouldn't warn on identity equals)
2486e9e: dfa: merge several states to account for variables with several possible values
4d4f4b0: dfa: some minor things and caching
c14961f: UnorderedPair in platform
5ad442d: Merge remote-tracking branch 'origin/master'
946a281: Scroll to bottom on typing in terminal (PY-10344).
e5a0548: Close all connections on dispose.
f61f6a2: changes from tech-writers
b82b0bb: dfa: state merging interruptibility
3893373: VcsDirtyScopeManagerImpl: log who marks everything dirty
41e5381: Merge remote-tracking branch 'origin/master'
da21efb: JediTerm updated.
beb1d1a: Merge remote-tracking branch 'origin/master'
ed3a2b5: skip the whole document if some component has disabled roaming type (details CR-IU-308)
d66309b: Fix antialiasing.
e55fae1: dfa: abstract out eq class into EqClass class
370d44d: dfa: remove trivial state facts that constant != another constant
4ccfcf7: UsagesStatistic must specify roaming disabled
75894ae: cleanup
784b4e3: DimensionService: cleanup, order of stored data should be stable
36443b6: overrides
b70b1dc: overrides
dfe38fb: simplify some constant conditions and greenify
9a08478: IDEA-85961 (Pattern BACKSLASH_PATTERN = Pattern.compile("\\", Pattern.LITERAL) is always marked red.)
d0bdc3b: simplify load from providers – we don't need to filter again (our save do it, in any case it is absurd to store component with global roaming in the project level file, — should be refine later)
bf85e1b: cleanup
9c30823: remove unused methods
f671c09: overrides
3bd62bc: ComponentRoamingManager should not keep defaults (we use RoamingType.PER_USER by default)
a8f1063: CR-IU-300 remove outdated EP ComponentRoamingType
b182751: CR-IU-300 remove outdated RoamingTypePerPlatform
994389c: another java.util.regex.Pattern.compile() parameter annotation
301710d: IDEA-113866 (this. not suggested for fields of anonymous inner classes)
f5d03c4: dfa: don't consider final getters same as immutable fields
272a6d0: Corresponding parents for console colors.
71298ce: Bright console colors for Monokai.
f39c34b: Console colors for WarmNeon scheme.
7548e47: Black is invisible on dark background (in RegExps for example).
ca6b784: Change bloody red to light pink for numbers (pink is specific to Neon color schemes while red is not, also eyes say thanks).
7f627d9: Console colors for Twilight scheme fixed.
a5eb2fc: Console colors for Monokai scheme fixed.
f7da145: DfaPsiType: add @NotNull
b216102: rebomb test
b349547: diagnostics for inconsistencies during control flow building
6823425: dfa: only perform costly state merging when it has chances - after jumps
fea8871: dfa: fighting too complex methods; join complementary memory states after fork to avoid having too many states
0ac2084: DfaMemoryStateImpl: introduce unwrap; compare variable values with their non-initialized counterparts
e919b8b: dfa: only goto catch on non-trivial method calls and throws
e2ea04f: new inference: initial method reference constraint
a9dde36: new inference: check substituted descriptor return type
3e5b164: new inference: expression inside condition should be poly, target type for conditional expression
ff9f2e9: new inference: emulate fresh variable - do not override vars with captured ones
f415702: new inference: default constructor as poly expression argument
ee56497: new inference: symmetric variable bounds
4a46b24: new inference: init inter call inference
06829c5: Merge remote-tracking branch 'origin/master'
e3f213f: Console colors for Darcula.
f748505: IDEA-57940 Cyclic expand word should take into account all open files
460ef47: StreamProvider.isVersioningRequired
8029f47: Bright yellow made more visible on white background.
96006be: Default console colors as in xterm palette, gray and dark gray from standard vga palette for better readability.
a378414: Bight console colors added to settings.
54e6582: builder-based project types
b0b2cf8: template-based project types?
e741484: CPU hogging fix again
eb22a99: fix todo duplication when several pattern match -> prefer finding match with last pattern (in settings list), thus default TODO pattern is matched last
a4d4371: fix compilation
2f823ba: Difference Groovy Shell & Groovy Console actions
3e876f4: IDEA-113590 annotations as annotation values
732cafd: dead code
a712f87: pull up 'isQualified()' method
4edd102: extract base class from PullUpDialog
10d89d6: remove obsolete test
a0750e4: delete envFile manually
114cbb2: IDEA-113861 Gradle: it could be possible to hide 'Gradle: download' progress to the background
ca416b8: 'More' element for classes, files, action, and settings. Better renderer.
b2a550c: test framework: drop temp directory on light project close
8aaf53b: greenify ActionsTreeUtil a bit
922d41a: layout
2cd7326: adding frameworks support
2bd8fb0: cleanup
4ea6442: ProjectSummaryStep
9fdcdcd: commit project name
bd39918: new project wizard: first test
630fc14: External system: use URLs in compile output paths
85dbe5f: IDEA-65114 "Add Maven projects" cannot be undone
5041ae5: test framework: returning of the data provider
16e2072: @Nullable XBreakpoint.getProperties reverted +review CR-IC-2418
df4da38: dump shell environment to a temporary file to reduce probability of malformed lines occurrence
280d52a: let event log warning color be orange (IDEA-113802)
a30b2ae: IDEA-113836 Console folding: add TestNG related patterns
cbeb0f1: don't change mouse cursor during goto name population (IDEA-113800)
fb5ad5b: IDEA-113638 ChooseByName restart on write action spawns a new thread
89b3767: disable autopopup in groovy shell if selection by chars is enabled (IDEA-112820)
9fa36be: CompletionConfidence: don't force API users to implement unused method
34cf7eb: Console Folding: proper capitalization
5e8aa44: IDEA-113855 Search Everywhere looks scrambled at first start
71723cb: svn: Refactored executable validation - use separate version client
1114cfe: javadoc
0738800: jps model: simplification, source roots always have default properties
b1d5062: jps model: JpsElementType converted to interface to allow reusing common base class
229deb0: test framework: ok, put light project file into ephemeral directory, but keep it for a project's life
6e8b950: ensure "thread" suspend policy for logging breakpoints
d67c04e: EA-49809 Move client factories creation to SvnVcs constructor (instead of active() method)
935cdba: new inference: initial tests
970a180: encapsulate read access to USE_COMPILE_SERVER option
b9b3fc8: remote agents - extract to remote servers
cfe8e2b: WEB-9335 Bad insert pair brace in CSS
2815c22: WEB-9334 Incremental selection works bad with negative CSS values
d023471: new "Unnecessary unicode escape sequence" inspection
945b069: unicode escape needs at least one 'u'
8e7797b: chrome still crashed, revert to old, not-recursive speed search
1917d86: Merge remote-tracking branch 'origin/master'
c18e6bd: Lense mode "internal" preview
db88427: Merge branch 'svn1_8_new'
7c64e8b: test framework: do not put light project file into ephemeral directory
af09e11: remove @Nullable from key.get as it's too generic
d49df32: svn: Refactored prompting for working copy format - make return not null format
d6086ae: dfa: types with wildcard parameters are not equal
3d28aa5: Optimization: check exiting of griffon-app first
b016c04: correct ephemeral state copy (IDEA-113143 Calling method with contract shouldn't result in nullability suspicion)
189573f: svn: Refactored upgrade working copy format dialog - use list of available formats (instead of separate fields for each format)
60c471b: Rename test
1a42f59: Remove using of unnecessary StringBuilder
a56db90: Use MultiMap
340cf22: Calling method with contract shouldn't result in nullability suspicion (IDEA-113763, IDEA-113699, almost IDEA-113143)
f2a563b: dfa: unify nullability violation processing
709af86: dfa: expand contract test
1cddfb4: dfa cleanup: skipping reports on method calls is now done via unknown variable mechanism
2765dab: dfa: spare some minor cpu cycles
8bc7465: svn: Added "1.8" option to upgrade/checkout dialogs
c266bd2: IDEA-66603 Maven3: provide inspection that checks duplicate declarations of plugins
af32923: SpellChecker: "cyclomatic"
5f4f98f: svn: Refactored working copy format selection dialog to use WorkingCopyFormat instances instead of just strings
e33b58b: MismatchedCollectionQueryUpdateInspection -- added "compute" prefix (from j.u.Map in JDK8)
7d54b2e: new inference: accept nonProper eq bounds
457d95b: new inference: distinguish different captures
5b5f52e: new inference: assertions caused by raw types
3848de4: new inference: open top level captured wildcards
35d59c0: new inference: extend usage of already inferred variables
4f7b572: new inference: inference of calls in arguments during outer call inference
bfa7879: new inference: captured variables from outer calls to be included
ed95269: new inference: eq bound for S<=T constraint reduction
12a0faf: better positioning
13029b7: different position layout algorithms
39e6e21: EA-49923 - Fixed working copy format detection for default project
d521e9d: JDK combobox should show JDK home
17fe05e: Fix typo
7ab769b: IDEA-16077 Maven embedder runs in the 'wrong' JDK add "embedder JDK" option
418ddc0: Inline string constant
6a8f1e2: IDEA-16077 Maven embedder runs in the 'wrong' JDK extract MavenJdkCombobox
46078c4: svn: Refactored detection if command line implementation should be used (use utility method)
24106fc: XDebugger: @Nullable XBreakpoint.getProperties()
3dc6f07: extract util method
476dac4: Reinit checkbox state on create
39cf1fd: Structure viewer for simple editors support fixed
a38a251: Show filters only for table editor + a few model and UI fixes
cbd5630: Initial dynamic filters model + columns header improved
281c008: svn: Support nullable SVNStatusClient in status implementation for SVNKit
1840d42: simplification
fbcba0f: svn: Make command line clients (info, status) use vcs instead of project instances
ae8b41b: Merge remote-tracking branch 'origin/master'
a97397c: Extract method.
3b9eca4: new project wizard: preparing test infrastructure
327ddb0: Lense mode "internal" preview
0ede5e1: new project wizard: AbstractProjectWizard extracted
a94b556: IDEA-111335 Gradle: task tree is incorrectly displayed if tasks are added to sub-projects via 'subprojects' method
bfd366f: Merge remote-tracking branch 'origin/master'
0ef2a82: calls to obsolete method removed from build scripts
2df016f: AntLoggerFactory inner class made static to fix NoSuchMethodException in Logger.setFactory
fe876e2: svn: Clients for update command renamed and moved to corresponding package
a38d90e: Terminal color settings.
bd285b8: svn: Refactored update logic to common ClientFactory model
9cc13da: platform: ignore hidden Windows files
d87664c: test framework: relic property dropped
5f6ef06: svn: Removed unused "common ancestor" behavior from command line update client
3667fe1: Find in strings with reg exp with start / end match markers doesn't work without string delimiters (IDEA-113788)
94a079f: svn: Refactored "update" command - explicitly create new SVNKit update client for each update/switch operation
0344e91: new project wizard: added option to use framework libraries from an app server
2882ac0: svn: Removed unused methods from "update" client
17ea275: svn: Removed unused SvnProxies class
c926181: WEB-9342 External Tool fails on OSX if an executable file basename specified
a3433f9: svn: Removed unused methods from "info" client
ec3112d: Optimize SassExtensionFunctionsIndex
9f1abf7: nosplash shouldn't prevent from plugin update
4c7154d: dfa: use cached nullability
b81e9c3: dfa: less frequent "too long" check
0b0eba9: DfaValueFactory: use List instead of TIntObjectHashMap for sequential keys
95d5433: introduce DfaPsiType without nullability, to quickly check assignability/convertibility in DfaVariableState
b901d90: IDEA-96713 Incorrect options shown for 'implements'
e02e2c4: IDEA-113780 "Annotate" from history fixed for renamed/moved files
fe00f73: test framework: stability improvements
76d664d: platform: suspicious event logging
b204bdf: Cleanup (de-duplication)
7ba9ff0: spelling
ece939c: make public for Upsource
496db4d: xdebugger: rebuild standalone variables view on EDT
eae27cb: xdebugger: supported rebuilding of standalone variables view
8bf5204: xdebugger api: added convenient method
43dbb6f: Terminal options.
3db1f5c: Blink period and antialiasing settings.
88264bd: IDEA-108147 Use "merge sources" wrapper object instead of just string representation as data model for "Merge Sources" column (to correctly get file revision object and show details panel)
111e6ba: IDEA-108147 While building history for element make check "if element parent or child was changed in given revision" only be performed for non-"merge source" revisions
e07828d: svn: Implemented support for "merged revisions" parsing in history logic for command line
1586c4a: svn: history logic refactored for command line - get and parse history data in xml format
0ac1dd2: IDEA-94942 Refactored "Annotate" implementation for command line - use utility method for parsing
ba1e5e0: IDEA-94942 Implemented merge history support for "Annotate" action
4c3b0a8: IDEA-94942 Implemented "Switch" logic (during update)
Change-Id: I7092ae66ff47d353a5b9770d1d91f77369bb7734
Diffstat (limited to 'java/java-psi-impl/src/com/intellij/psi')
22 files changed, 847 insertions, 122 deletions
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java index bc62cc802fad..103b828b1873 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java @@ -799,7 +799,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme @Override public void processVariants(@NotNull final PsiScopeProcessor processor) { final OrFilter filter = new OrFilter(); - if (isInCode() && !(getParent() instanceof PsiImportStatement)) { + if (isInCode() && !(getParent() instanceof PsiImportStatement) && !(getParent() instanceof PsiReferenceList)) { filter.addFilter(new AndFilter(ElementClassFilter.METHOD, new NotFilter(new ConstructorFilter()))); filter.addFilter(ElementClassFilter.VARIABLE); } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java index 68bb8b865c92..15aba8821ffe 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java @@ -15,6 +15,7 @@ */ package com.intellij.psi.impl.source.resolve; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.registry.Registry; import com.intellij.pom.java.LanguageLevel; @@ -196,7 +197,16 @@ public class PsiResolveHelperImpl implements PsiResolveHelper { .getSubstitutionForTypeParameter(typeParam, param, arg, isContraVariantPosition, languageLevel); } + private PsiInferenceHelper myTestHelper; + + public void setTestHelper(PsiInferenceHelper testHelper) { + myTestHelper = testHelper; + } + public PsiInferenceHelper getInferenceHelper(LanguageLevel languageLevel) { + if (ApplicationManager.getApplication().isUnitTestMode()) { + return myTestHelper != null ? myTestHelper : new PsiOldInferenceHelper(myManager); + } if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8) && Registry.is("enable.graph.inference", false)) { return new PsiGraphInferenceHelper(myManager); } 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 new file mode 100644 index 000000000000..4806a51a5dcf --- /dev/null +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/FunctionalInterfaceParameterizationUtil.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.intellij.psi.impl.source.resolve.graphInference; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.psi.*; +import com.intellij.psi.impl.source.resolve.graphInference.constraints.TypeEqualityConstraint; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class FunctionalInterfaceParameterizationUtil { + private static final Logger LOG = Logger.getInstance("#" + FunctionalInterfaceParameterizationUtil.class.getName()); + + public static boolean isWildcardParameterized(@Nullable PsiType classType) { + if (classType == null) return false; + if (classType instanceof PsiIntersectionType) { + for (PsiType type : ((PsiIntersectionType)classType).getConjuncts()) { + if (!isWildcardParameterized(type)) return false; + } + } + if (classType instanceof PsiClassType) { + for (PsiType type : ((PsiClassType)classType).getParameters()) { + if (type instanceof PsiWildcardType || type instanceof PsiCapturedWildcardType) { + return true; + } + } + return false; + } + LOG.error("Unexpected type: " + classType); + return false; + } + + @Nullable + public static PsiType getFunctionalType(@Nullable PsiType psiClassType, PsiLambdaExpression expr) { + if (!expr.hasFormalParameterTypes() || expr.getParameterList().getParametersCount() == 0) return psiClassType; + if (!isWildcardParameterized(psiClassType)) { + return psiClassType; + } + final PsiParameter[] lambdaParams = expr.getParameterList().getParameters(); + if (psiClassType instanceof PsiIntersectionType) { + for (PsiType psiType : ((PsiIntersectionType)psiClassType).getConjuncts()) { + final PsiType functionalType = getFunctionalType(psiType, expr); + if (functionalType != null) return functionalType; + } + return null; + } + + LOG.assertTrue(psiClassType instanceof PsiClassType, "Unexpected type: " + psiClassType); + final PsiType[] parameters = ((PsiClassType)psiClassType).getParameters(); + final PsiClassType.ClassResolveResult resolveResult = ((PsiClassType)psiClassType).resolveGenerics(); + PsiClass psiClass = resolveResult.getElement(); + + if (psiClass != null) { + + 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(); + for (int i = 0; i < targetMethodParams.length; i++) { + session.addConstraint(new TypeEqualityConstraint(lambdaParams[i].getType(), targetMethodParams[i].getType())); + } + + final PsiClassType parameterization = elementFactory.createType(psiClass, session.infer()); + if (!isWildcardParameterized(parameterization)) return parameterization; + } + return null; + } +} diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceIncorporationPhase.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceIncorporationPhase.java index a63e43824986..e1c3d63d8b15 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 @@ -174,8 +174,10 @@ public class InferenceIncorporationPhase { private void eqEq(List<PsiType> eqBounds) { for (int i = 0; i < eqBounds.size(); i++) { PsiType sBound= eqBounds.get(i); + if (sBound == null) continue; for (int j = i + 1; j < eqBounds.size(); j++) { final PsiType tBound = eqBounds.get(j); + if (tBound == null) continue; addConstraint(new TypeEqualityConstraint(tBound, sBound)); } } 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 dba4a7289a5e..df785073a6d7 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 @@ -18,13 +18,17 @@ package com.intellij.psi.impl.source.resolve.graphInference; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Pair; import com.intellij.psi.*; +import com.intellij.psi.impl.PsiImplUtil; +import com.intellij.psi.impl.source.resolve.graphInference.constraints.CheckedExceptionCompatibilityConstraint; import com.intellij.psi.impl.source.resolve.graphInference.constraints.ConstraintFormula; import com.intellij.psi.impl.source.resolve.graphInference.constraints.ExpressionCompatibilityConstraint; import com.intellij.psi.impl.source.resolve.graphInference.constraints.TypeCompatibilityConstraint; import com.intellij.psi.infos.MethodCandidateInfo; 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 org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -38,7 +42,6 @@ public class InferenceSession { private Map<PsiTypeParameter, InferenceVariable> myInferenceVariables = new LinkedHashMap<PsiTypeParameter, InferenceVariable>(); private final List<ConstraintFormula> myConstraints = new ArrayList<ConstraintFormula>(); - private final List<ConstraintFormula> myDelayedConstraints = new ArrayList<ConstraintFormula>(); private PsiSubstitutor mySiteSubstitutor; private PsiManager myManager; @@ -46,6 +49,10 @@ public class InferenceSession { private final InferenceIncorporationPhase myIncorporationPhase = new InferenceIncorporationPhase(this); + public InferenceSession(PsiSubstitutor siteSubstitutor) { + mySiteSubstitutor = siteSubstitutor; + } + public InferenceSession(PsiTypeParameter[] typeParams, PsiType[] leftTypes, PsiType[] rightTypes, @@ -75,14 +82,10 @@ public class InferenceSession { if (parameters.length > 0) { for (int i = 0; i < args.length; i++) { - PsiType parameterType = mySiteSubstitutor.substitute(parameters[i < parameters.length ? i : parameters.length - 1].getType()); - if (parameterType instanceof PsiEllipsisType) { - if (args.length != parameters.length || args[i] != null && !(args[i].getType() instanceof PsiArrayType)) { - parameterType = ((PsiEllipsisType)parameterType).getComponentType(); - } - } + PsiType parameterType = getParameterType(parameters, args, i, mySiteSubstitutor); if (args[i] != null) { myConstraints.add(new ExpressionCompatibilityConstraint(args[i], parameterType)); + //myConstraints.add(new CheckedExceptionCompatibilityConstraint(args[i], parameterType)); } } } @@ -98,11 +101,66 @@ public class InferenceSession { } } + public static boolean isPertinentToApplicability(PsiExpression expr, PsiMethod method) { + if (expr instanceof PsiLambdaExpression) { + if (((PsiLambdaExpression)expr).hasFormalParameterTypes()) return true; + for (PsiExpression expression : LambdaUtil.getReturnExpressions((PsiLambdaExpression)expr)) { + if (!isPertinentToApplicability(expression, method)) return false; + } + if (method.getTypeParameters().length > 0) { + final PsiElement parent = PsiUtil.skipParenthesizedExprUp(expr.getParent()); + if (parent instanceof PsiExpressionList) { + final PsiElement gParent = parent.getParent(); + if (gParent instanceof PsiCallExpression && ((PsiCallExpression)gParent).getTypeArgumentList().getTypeParameterElements().length == 0) { + final int idx = LambdaUtil.getLambdaIdx(((PsiExpressionList)parent), expr); + final PsiParameter[] parameters = method.getParameterList().getParameters(); + PsiType paramType; + if (idx > parameters.length - 1) { + final PsiType lastParamType = parameters[parameters.length - 1].getType(); + paramType = parameters[parameters.length - 1].isVarArgs() ? ((PsiEllipsisType)lastParamType).getComponentType() : lastParamType; + } + else { + paramType = parameters[idx].getType(); + } + final PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(paramType); + if (psiClass instanceof PsiTypeParameter && ((PsiTypeParameter)psiClass).getOwner() == method) return false; + } + } + } + return true; + } + if (expr instanceof PsiMethodReferenceExpression) { + return ((PsiMethodReferenceExpression)expr).isExact(); + } + if (expr instanceof PsiParenthesizedExpression) { + return isPertinentToApplicability(((PsiParenthesizedExpression)expr).getExpression(), method); + } + if (expr instanceof PsiConditionalExpression) { + final PsiExpression thenExpression = ((PsiConditionalExpression)expr).getThenExpression(); + if (!isPertinentToApplicability(thenExpression, method)) return false; + final PsiExpression elseExpression = ((PsiConditionalExpression)expr).getElseExpression(); + if (!isPertinentToApplicability(elseExpression, method)) return false; + } + return true; + } + + private static PsiType getParameterType(PsiParameter[] parameters, PsiExpression[] args, int i, PsiSubstitutor substitutor) { + PsiType parameterType = substitutor.substitute(parameters[i < parameters.length ? i : parameters.length - 1].getType()); + if (parameterType instanceof PsiEllipsisType) { + if (args.length != parameters.length || PsiPolyExpressionUtil + .isPolyExpression(args[i]) || args[i] != null && !(args[i].getType() instanceof PsiArrayType)) { + parameterType = ((PsiEllipsisType)parameterType).getComponentType(); + } + } + return parameterType; + } + @NotNull public PsiSubstitutor infer() { repeatInferencePhases(); for (InferenceVariable inferenceVariable : myInferenceVariables.values()) { + if (inferenceVariable.isCaptured()) continue; final PsiTypeParameter typeParameter = inferenceVariable.getParameter(); PsiType instantiation = inferenceVariable.getInstantiation(); if (instantiation == PsiType.NULL) { @@ -136,25 +194,60 @@ public class InferenceSession { } } } + + public void addCapturedVariable(PsiTypeParameter param) { + if (myInferenceVariables.containsKey(param)) return; //same method call + final InferenceVariable variable = new InferenceVariable(param); + variable.setCaptured(true); + myInferenceVariables.put(param, variable); + } private void initReturnTypeConstraint(PsiMethod method, PsiCallExpression context) { if (PsiPolyExpressionUtil.isPolyExpression(context) || context instanceof PsiNewExpression && PsiDiamondType.ourDiamondGuard.currentStack().contains(context)) { final PsiType returnType = method.getReturnType(); if (!PsiType.VOID.equals(returnType) && returnType != null) { - final PsiType targetType = PsiPolyExpressionUtil.getTargetType(context);//todo primitive type + PsiType targetType = PsiTypesUtil.getExpectedTypeByParent(context); + if (targetType == null) { + final PsiElement parent = PsiUtil.skipParenthesizedExprUp(context.getParent()); + if (parent instanceof PsiExpressionList) { + final PsiElement gParent = parent.getParent(); + if (gParent instanceof PsiCallExpression) { + final PsiExpressionList argumentList = ((PsiCallExpression)gParent).getArgumentList(); + if (argumentList != null) { + final JavaResolveResult resolveResult = ((PsiCallExpression)gParent).resolveMethodGenerics(); + final PsiElement parentMethod = resolveResult.getElement(); + if (parentMethod instanceof PsiMethod) { + final PsiParameter[] parameters = ((PsiMethod)parentMethod).getParameterList().getParameters(); + PsiElement arg = context; + while (arg.getParent() instanceof PsiParenthesizedExpression) { + arg = parent.getParent(); + } + final PsiExpression[] args = argumentList.getExpressions(); + targetType = getParameterType(parameters, args, ArrayUtilRt.find(args, arg), resolveResult.getSubstitutor()); + } + } + } + } else if (parent instanceof PsiConditionalExpression) { + targetType = PsiTypesUtil.getExpectedTypeByParent((PsiExpression)parent); + } + } if (targetType != null) { - myConstraints.add(new TypeCompatibilityConstraint(targetType, returnType)); + myConstraints.add(new TypeCompatibilityConstraint(targetType, PsiImplUtil.normalizeWildcardTypeByPosition(returnType, context))); } } } } public InferenceVariable getInferenceVariable(PsiType psiType) { + return getInferenceVariable(psiType, true); + } + + public InferenceVariable getInferenceVariable(PsiType psiType, boolean acceptCaptured) { final PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(psiType); if (psiClass instanceof PsiTypeParameter) { final InferenceVariable inferenceVariable = myInferenceVariables.get(psiClass); - if (inferenceVariable != null) { + if (inferenceVariable != null && (acceptCaptured || !inferenceVariable.isCaptured())) { return inferenceVariable; } } @@ -162,10 +255,16 @@ public class InferenceSession { } public boolean isProperType(@Nullable PsiType type) { - return collectDependencies(type, null); + return isProperType(type, true); } - public boolean collectDependencies(@Nullable PsiType type, @Nullable final Set<InferenceVariable> dependencies) { + public boolean isProperType(@Nullable PsiType type, boolean acceptCaptured) { + return collectDependencies(type, null, acceptCaptured); + } + + public boolean collectDependencies(@Nullable PsiType type, + @Nullable final Set<InferenceVariable> dependencies, + final boolean acceptCaptured) { if (type == null) return true; final Boolean isProper = type.accept(new PsiTypeVisitor<Boolean>() { @Nullable @@ -191,7 +290,7 @@ public class InferenceSession { @Nullable @Override public Boolean visitClassType(PsiClassType classType) { - final InferenceVariable inferenceVariable = getInferenceVariable(classType); + final InferenceVariable inferenceVariable = getInferenceVariable(classType, acceptCaptured); if (inferenceVariable != null) { if (dependencies != null) { dependencies.add(inferenceVariable); @@ -225,7 +324,7 @@ public class InferenceSession { List<ConstraintFormula> newConstraints = new ArrayList<ConstraintFormula>(); for (int i = myConstraintIdx; i < myConstraints.size(); i++) { ConstraintFormula constraint = myConstraints.get(i); - if (!constraint.reduce(this, newConstraints, myDelayedConstraints)) { + if (!constraint.reduce(this, newConstraints)) { return false; } } @@ -241,7 +340,7 @@ public class InferenceSession { for (List<InferenceVariable> variables : independentVars) { for (InferenceVariable inferenceVariable : variables) { - if (inferenceVariable.getInstantiation() != PsiType.NULL) continue; + if (inferenceVariable.isCaptured() || inferenceVariable.getInstantiation() != PsiType.NULL) continue; final PsiTypeParameter typeParameter = inferenceVariable.getParameter(); try { final List<PsiType> eqBounds = inferenceVariable.getBounds(InferenceBound.EQ); @@ -253,19 +352,18 @@ public class InferenceSession { } PsiType bound = null; for (PsiType eqBound : eqBounds) { - eqBound = acceptBoundsWithRecursiveDependencies(typeParameter, eqBound); - if (isProperType(eqBound)) { - bound = eqBound; - break; - } + bound = acceptBoundsWithRecursiveDependencies(typeParameter, eqBound); } if (bound != null) { + if (bound instanceof PsiCapturedWildcardType && eqBounds.size() > 1) { + continue; + } inferenceVariable.setInstantiation(bound); } else { PsiType lub = null; for (PsiType lowerBound : lowerBounds) { lowerBound = acceptBoundsWithRecursiveDependencies(typeParameter, lowerBound); - if (isProperType(lowerBound)) { + if (isProperType(lowerBound, false)) { if (lub == null) { lub = lowerBound; } @@ -281,7 +379,7 @@ public class InferenceSession { PsiType glb = null; for (PsiType upperBound : upperBounds) { upperBound = acceptBoundsWithRecursiveDependencies(typeParameter, upperBound); - if (isProperType(upperBound)) { + if (isProperType(upperBound, false)) { if (glb == null) { glb = upperBound; } @@ -307,8 +405,9 @@ public class InferenceSession { } private PsiType acceptBoundsWithRecursiveDependencies(PsiTypeParameter typeParameter, PsiType bound) { - if (PsiPolyExpressionUtil.mentionsTypeParameters(bound, Collections.singleton(typeParameter))) { - return mySiteSubstitutor.put(typeParameter, null).substitute(bound); + if (!isProperType(bound)) { + final PsiSubstitutor substitutor = PsiUtil.resolveClassInType(bound) != typeParameter ? mySiteSubstitutor.put(typeParameter, null) : mySiteSubstitutor; + return substitutor.substitute(bound); } return bound; } @@ -330,4 +429,24 @@ public class InferenceSession { myConstraints.add(constraint); } } + + public Collection<PsiTypeParameter> getTypeParams() { + 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(), parameter.getResolveScope()), + InferenceBound.UPPER); + } + } else { + variable.addBound(parameter, InferenceBound.EQ); + } + myInferenceVariables.put(typeParameter, variable); + } } 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 e69f229fe91f..f750e1247728 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 @@ -58,7 +58,8 @@ public class InferenceVariable { list = new ArrayList<PsiType>(); myBounds.put(inferenceBound, list); } - if (!list.contains(classType)) { + final int idx = list.indexOf(classType); + if (idx < 0 || inferenceBound == InferenceBound.EQ && classType instanceof PsiCapturedWildcardType && list.get(idx) != classType) { list.add(classType); return true; } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariablesOrder.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariablesOrder.java index 4a2c4126611e..c27ae4a53916 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariablesOrder.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariablesOrder.java @@ -41,7 +41,7 @@ public class InferenceVariablesOrder { for (InferenceBound inferenceBound : InferenceBound.values()) { for (PsiType bound : var.getBounds(inferenceBound)) { final HashSet<InferenceVariable> dependencies = new HashSet<InferenceVariable>(); - session.collectDependencies(bound, dependencies); + session.collectDependencies(bound, dependencies, true); for (InferenceVariable dependentVariable : dependencies) { final InferenceGraphNode<InferenceVariable> dependency = nodes.get(dependentVariable); if (dependency != null) { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/PsiPolyExpressionUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/PsiPolyExpressionUtil.java index 2e425e0fb436..d6a1d46ad336 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/PsiPolyExpressionUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/PsiPolyExpressionUtil.java @@ -82,10 +82,6 @@ public class PsiPolyExpressionUtil { return false; } - public static PsiType getTargetType(@NotNull PsiCallExpression expression) { - return PsiTypesUtil.getExpectedTypeByParent(expression); - } - public static Boolean mentionsTypeParameters(@Nullable PsiType returnType, final Set<PsiTypeParameter> typeParameters) { if (returnType == null) return false; return returnType.accept(new PsiTypeVisitor<Boolean>() { @@ -125,7 +121,7 @@ public class PsiPolyExpressionUtil { private static boolean isInAssignmentOrInvocationContext(PsiExpression expr) { final PsiElement context = expr.getParent(); - return context instanceof PsiExpressionList || isAssignmentContext(expr, context); + return context instanceof PsiExpressionList || context instanceof PsiConditionalExpression || isAssignmentContext(expr, context); } private static boolean isAssignmentContext(PsiExpression expr, PsiElement context) { 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 new file mode 100644 index 000000000000..19f50e6fd412 --- /dev/null +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java @@ -0,0 +1,164 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS 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.codeInsight.ExceptionUtil; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.psi.*; +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 com.intellij.psi.util.TypeConversionUtil; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * User: anna + */ +public class CheckedExceptionCompatibilityConstraint extends InputOutputConstraintFormula { + private static final Logger LOG = Logger.getInstance("#" + CheckedExceptionCompatibilityConstraint.class.getName()); + private final PsiExpression myExpression; + private final PsiType myT; + + public CheckedExceptionCompatibilityConstraint(PsiExpression expression, PsiType t) { + myExpression = expression; + myT = t; + } + + @Override + public boolean reduce(InferenceSession session, List<ConstraintFormula> constraints) { + if (!PsiPolyExpressionUtil.isPolyExpression(myExpression) || + myExpression instanceof PsiCallExpression) { + return true; + } + if (myExpression instanceof PsiParenthesizedExpression) { + constraints.add(new CheckedExceptionCompatibilityConstraint(((PsiParenthesizedExpression)myExpression).getExpression(), myT)); + return true; + } + if (myExpression instanceof PsiConditionalExpression) { + final PsiExpression thenExpression = ((PsiConditionalExpression)myExpression).getThenExpression(); + if (thenExpression != null) { + constraints.add(new CheckedExceptionCompatibilityConstraint(thenExpression, myT)); + } + final PsiExpression elseExpression = ((PsiConditionalExpression)myExpression).getElseExpression(); + if (elseExpression != null) { + constraints.add(new CheckedExceptionCompatibilityConstraint(elseExpression, myT)); + } + return true; + } + if (myExpression instanceof PsiLambdaExpression || myExpression instanceof PsiMethodReferenceExpression) { + if (LambdaHighlightingUtil.checkInterfaceFunctional(myT) != null) { + return false; + } + final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(myT); + if (interfaceMethod == null) { + return false; + } + + final PsiSubstitutor substitutor = LambdaUtil.getSubstitutor(interfaceMethod, PsiUtil.resolveGenericsClassInType(myT)); + for (PsiParameter parameter : interfaceMethod.getParameterList().getParameters()) { + if (!session.isProperType(substitutor.substitute(parameter.getType()))) return false; + } + final PsiType returnType = interfaceMethod.getReturnType(); + LOG.assertTrue(returnType != null, interfaceMethod); + if (!session.isProperType(substitutor.substitute(returnType))) return false; + + final List<PsiType> + expectedThrownTypes = ContainerUtil.map(interfaceMethod.getThrowsList().getReferencedTypes(), new Function<PsiType, PsiType>() { + @Override + public PsiType fun(PsiType type) { + return substitutor.substitute(type); + } + }); + final List<PsiType> expectedNonProperThrownTypes = new ArrayList<PsiType>(); + for (PsiType type : expectedThrownTypes) { + if (!session.isProperType(type)) { + expectedNonProperThrownTypes.add(type); + } + } + + final List<PsiType> thrownTypes = new ArrayList<PsiType>(); + if (myExpression instanceof PsiLambdaExpression) { + //todo + } else { + final PsiElement resolve = ((PsiMethodReferenceExpression)myExpression).resolve(); + if (resolve instanceof PsiMethod) { + for (PsiClassType type : ((PsiMethod)resolve).getThrowsList().getReferencedTypes()) { + if (!ExceptionUtil.isUncheckedException(type)) { + thrownTypes.add(type); + } + } + } + } + + if (expectedNonProperThrownTypes.isEmpty()) { + for (PsiType thrownType : thrownTypes) { + if (!isAddressed(expectedThrownTypes, thrownType)) return false; + } + } else { + final ArrayList<PsiType> expectedProperTypes = new ArrayList<PsiType>(expectedThrownTypes); + expectedProperTypes.retainAll(expectedNonProperThrownTypes); + for (PsiType thrownType : thrownTypes) { + if (!isAddressed(expectedProperTypes, thrownType)) { + for (PsiType expectedNonProperThrownType : expectedNonProperThrownTypes) { + constraints.add(new TypeCompatibilityConstraint(expectedNonProperThrownType, thrownType)); + } + } + } + } + } + + return true; + } + + private static boolean isAddressed(List<PsiType> expectedThrownTypes, PsiType thrownType) { + for (PsiType expectedThrownType : expectedThrownTypes) { + if (TypeConversionUtil.isAssignable(expectedThrownType, thrownType)) { + return true; + } + } + return false; + } + + @Override + protected PsiExpression getExpression() { + return myExpression; + } + + @Override + protected PsiType getT() { + return myT; + } + + @Override + protected InputOutputConstraintFormula createSelfConstraint(PsiType type, PsiExpression expression) { + return new CheckedExceptionCompatibilityConstraint(expression, type); + } + + @Override + protected void collectReturnTypeVariables(InferenceSession session, + PsiExpression psiExpression, + PsiMethod interfaceMethod, + Set<InferenceVariable> result) { + final PsiType returnType = interfaceMethod.getReturnType(); + session.collectDependencies(returnType, result, true); + } +} diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ConstraintFormula.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ConstraintFormula.java index 992d875bb535..8dc8ee034cc1 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ConstraintFormula.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ConstraintFormula.java @@ -23,5 +23,5 @@ import java.util.List; * User: anna */ public interface ConstraintFormula { - boolean reduce(InferenceSession session, List<ConstraintFormula> constraints, List<ConstraintFormula> delayedConstraints); + boolean reduce(InferenceSession session, List<ConstraintFormula> constraints); } 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 a0e6a767d8f2..7084538c17c7 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 @@ -15,18 +15,22 @@ */ package com.intellij.psi.impl.source.resolve.graphInference.constraints; +import com.intellij.openapi.util.Pair; import com.intellij.psi.*; 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.PsiMethodCallExpressionImpl; +import com.intellij.psi.infos.MethodCandidateInfo; import com.intellij.psi.util.TypeConversionUtil; import org.jetbrains.annotations.NotNull; -import java.util.List; +import java.util.*; /** * User: anna */ -public class ExpressionCompatibilityConstraint implements ConstraintFormula { +public class ExpressionCompatibilityConstraint extends InputOutputConstraintFormula { private PsiExpression myExpression; private PsiType myT; @@ -36,7 +40,7 @@ public class ExpressionCompatibilityConstraint implements ConstraintFormula { } @Override - public boolean reduce(InferenceSession session, List<ConstraintFormula> constraints, List<ConstraintFormula> delayedConstraints) { + public boolean reduce(InferenceSession session, List<ConstraintFormula> constraints) { if (session.isProperType(myT)) { return TypeConversionUtil.areTypesAssignmentCompatible(myT, myExpression); } @@ -69,11 +73,59 @@ public class ExpressionCompatibilityConstraint implements ConstraintFormula { } if (myExpression instanceof PsiCallExpression) { - //todo + final PsiExpressionList argumentList = ((PsiCallExpression)myExpression).getArgumentList(); + if (argumentList != null) { + final Map<PsiElement,Pair<PsiMethod,PsiSubstitutor>> map = MethodCandidateInfo.CURRENT_CANDIDATE.get(); + final Pair<PsiMethod,PsiSubstitutor> pair = map != null ? map.get(argumentList) : null; + final PsiMethod method = pair != null ? pair.first : ((PsiCallExpression)myExpression).resolveMethod(); + PsiType returnType = null; + InferenceSession callSession = null; + if (method != null) { + returnType = method.getReturnType(); + final PsiParameter[] parameters = method.getParameterList().getParameters(); + if (returnType != null) { + callSession = new InferenceSession(method.getTypeParameters(), parameters, + argumentList.getExpressions(), + PsiSubstitutor.EMPTY, null, myExpression.getManager()); + + } + } else if (myExpression instanceof PsiNewExpression) { //default constructor + final PsiJavaCodeReferenceElement classReference = ((PsiNewExpression)myExpression).getClassOrAnonymousClassReference(); + if (classReference != null) { + final PsiElement psiClass = classReference.resolve(); + if (psiClass instanceof PsiClass) { + returnType = JavaPsiFacade.getElementFactory(argumentList.getProject()).createType((PsiClass)psiClass, PsiSubstitutor.EMPTY); + callSession = new InferenceSession(((PsiClass)psiClass).getTypeParameters(), + PsiParameter.EMPTY_ARRAY, + argumentList.getExpressions(), + PsiSubstitutor.EMPTY, null, myExpression.getManager()); + } + } + } + + if (callSession != null) { + + for (PsiTypeParameter typeParameter : session.getTypeParams()) { + callSession.addCapturedVariable(typeParameter); + } + callSession.addConstraint(new TypeCompatibilityConstraint(myT, returnType)); + final PsiSubstitutor callSubstitutor = callSession.infer(); + + if (myExpression instanceof PsiMethodCallExpression) { + returnType = PsiMethodCallExpressionImpl.captureReturnType((PsiMethodCallExpression)myExpression, method, returnType, callSubstitutor); + } + else { + returnType = callSubstitutor.substitute(returnType); + } + constraints.add(new TypeCompatibilityConstraint(myT, returnType)); //todo primitive types + } + } + return true; } if (myExpression instanceof PsiMethodReferenceExpression) { - //todo + constraints.add(new PsiMethodReferenceCompatibilityConstraint(((PsiMethodReferenceExpression)myExpression), myT)); + return true; } if (myExpression instanceof PsiLambdaExpression) { @@ -104,4 +156,37 @@ public class ExpressionCompatibilityConstraint implements ConstraintFormula { result = 31 * result + myT.hashCode(); return result; } + + @Override + public PsiExpression getExpression() { + return myExpression; + } + + @Override + public PsiType getT() { + return myT; + } + + @Override + protected InputOutputConstraintFormula createSelfConstraint(PsiType type, PsiExpression expression) { + return new ExpressionCompatibilityConstraint(expression, type); + } + + protected void collectReturnTypeVariables(InferenceSession session, + PsiExpression psiExpression, + PsiMethod interfaceMethod, + Set<InferenceVariable> result) { + if (psiExpression instanceof PsiLambdaExpression) { + final PsiType returnType = interfaceMethod.getReturnType(); + if (returnType != PsiType.VOID) { + final List<PsiExpression> returnExpressions = LambdaUtil.getReturnExpressions((PsiLambdaExpression)psiExpression); + for (PsiExpression expression : returnExpressions) { + final Set<InferenceVariable> resultInputVars = createSelfConstraint(returnType, expression).getInputVariables(session); + if (resultInputVars != null) { + result.addAll(resultInputVars); + } + } + } + } + } } 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 new file mode 100644 index 000000000000..d06538c06b41 --- /dev/null +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/InputOutputConstraintFormula.java @@ -0,0 +1,112 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS 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.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; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +/** + * User: anna + * Date: 9/25/13 + */ +public abstract class InputOutputConstraintFormula implements ConstraintFormula { + + protected abstract PsiExpression getExpression(); + protected abstract PsiType getT(); + protected abstract InputOutputConstraintFormula createSelfConstraint(PsiType type, PsiExpression expression); + protected abstract void collectReturnTypeVariables(InferenceSession session, + PsiExpression psiExpression, + PsiMethod interfaceMethod, + Set<InferenceVariable> result); + + public Set<InferenceVariable> getInputVariables(InferenceSession session) { + final PsiExpression psiExpression = getExpression(); + if (PsiPolyExpressionUtil.isPolyExpression(psiExpression)) { + final PsiType type = getT(); + if (psiExpression instanceof PsiLambdaExpression || psiExpression instanceof PsiMethodReferenceExpression) { + final InferenceVariable inferenceVariable = session.getInferenceVariable(type); + if (inferenceVariable != null) { + return Collections.singleton(inferenceVariable); + } + final PsiType functionalInterfaceType = psiExpression instanceof PsiLambdaExpression + ? ((PsiLambdaExpression)psiExpression).getFunctionalInterfaceType() + : ((PsiMethodReferenceExpression)psiExpression).getFunctionalInterfaceType(); + if (functionalInterfaceType != null) { + final PsiType functionType = + psiExpression instanceof PsiLambdaExpression + ? FunctionalInterfaceParameterizationUtil.getFunctionalType(functionalInterfaceType, (PsiLambdaExpression)psiExpression) + : functionalInterfaceType; + final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionType); + final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult); + if (interfaceMethod != null) { + + final Set<InferenceVariable> result = new HashSet<InferenceVariable>(); + final PsiSubstitutor substitutor = LambdaUtil.getSubstitutor(interfaceMethod, resolveResult); + for (PsiParameter parameter : interfaceMethod.getParameterList().getParameters()) { + session.collectDependencies(substitutor.substitute(parameter.getType()), result, true); + } + + collectReturnTypeVariables(session, psiExpression, interfaceMethod, result); + + return result; + } + } + } + + if (psiExpression instanceof PsiParenthesizedExpression) { + final PsiExpression expression = ((PsiParenthesizedExpression)psiExpression).getExpression(); + return expression != null ? createSelfConstraint(type, expression).getInputVariables(session) : null; + } + + if (psiExpression instanceof PsiConditionalExpression) { + final PsiExpression thenExpression = ((PsiConditionalExpression)psiExpression).getThenExpression(); + final PsiExpression elseExpression = ((PsiConditionalExpression)psiExpression).getElseExpression(); + final Set<InferenceVariable> thenResult = thenExpression != null ? createSelfConstraint(type, thenExpression).getInputVariables(session) : null; + final Set<InferenceVariable> elseResult = elseExpression != null ? createSelfConstraint(type, elseExpression).getInputVariables(session) : null; + if (thenResult == null) { + return elseResult; + } else if (elseResult == null) { + return thenResult; + } else { + thenResult.addAll(elseResult); + return thenResult; + } + } + } + return null; + } + + + @Nullable + public Set<InferenceVariable> getOutputVariables(Set<InferenceVariable> inputVariables, InferenceSession session) { + if (!PsiPolyExpressionUtil.isPolyExpression(getExpression())) { + final HashSet<InferenceVariable> mentionedVariables = new HashSet<InferenceVariable>(); + session.collectDependencies(getT(), mentionedVariables, true); + mentionedVariables.removeAll(inputVariables); + return mentionedVariables; + } + return null; + } +} 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 9d9dad46ffc8..d7751754ab8b 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,8 +1,8 @@ package com.intellij.psi.impl.source.resolve.graphInference.constraints; import com.intellij.psi.*; +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.util.PsiUtil; import java.util.List; @@ -20,30 +20,21 @@ public class LambdaExpressionCompatibilityConstraint implements ConstraintFormul } @Override - public boolean reduce(InferenceSession session, List<ConstraintFormula> constraints, List<ConstraintFormula> delayedConstraints) { - final InferenceVariable inferenceVariable = session.getInferenceVariable(myT); - if (inferenceVariable != null) { - delayedConstraints.add(this); - return true; - } + public boolean reduce(InferenceSession session, List<ConstraintFormula> constraints) { if (LambdaHighlightingUtil.checkInterfaceFunctional(myT) != null) { return false; } if (myExpression.hasFormalParameterTypes()) { } - final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(myT); + final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType( + FunctionalInterfaceParameterizationUtil.getFunctionalType(myT, myExpression)); + final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult); if (interfaceMethod == null) { return false; } - final PsiSubstitutor substitutor = LambdaUtil.getSubstitutor(interfaceMethod, PsiUtil.resolveGenericsClassInType(myT)); + final PsiSubstitutor substitutor = LambdaUtil.getSubstitutor(interfaceMethod, resolveResult); final PsiParameter[] parameters = interfaceMethod.getParameterList().getParameters(); - for (PsiParameter parameter : parameters) { - if (!session.isProperType(parameter.getType())) { - delayedConstraints.add(this); - return true; - } - } final PsiParameter[] lambdaParameters = myExpression.getParameterList().getParameters(); if (lambdaParameters.length != parameters.length) { @@ -53,20 +44,27 @@ public class LambdaExpressionCompatibilityConstraint implements ConstraintFormul for (int i = 0; i < lambdaParameters.length; i++) { constraints.add(new TypeEqualityConstraint(lambdaParameters[i].getType(), substitutor.substitute(parameters[i].getType()))); } + } else { + for (PsiParameter parameter : parameters) { + if (!session.isProperType(substitutor.substitute(parameter.getType()))) { + return false; + } + } } final PsiType returnType = interfaceMethod.getReturnType(); if (returnType != null) { + final List<PsiExpression> returnExpressions = LambdaUtil.getReturnExpressions(myExpression); if (returnType.equals(PsiType.VOID)) { - if (!myExpression.isVoidCompatible() && !(myExpression.getBody() instanceof PsiExpression)) { + if (!returnExpressions.isEmpty() && !(myExpression.getBody() instanceof PsiExpression)) { return false; } } else { - if (myExpression.isVoidCompatible()) { //not value-compatible + if (returnExpressions.isEmpty()) { //not value-compatible return false; } - for (PsiExpression returnExpressions : LambdaUtil.getReturnExpressions(myExpression)) { - constraints.add(new ExpressionCompatibilityConstraint(returnExpressions, returnType)); + for (PsiExpression returnExpression : returnExpressions) { + constraints.add(new ExpressionCompatibilityConstraint(returnExpression, substitutor.substitute(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 new file mode 100644 index 000000000000..d1de66e453a8 --- /dev/null +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.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.resolve.graphInference.constraints; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.psi.*; +import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession; +import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil; +import com.intellij.psi.util.PsiUtil; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; + +/** + * User: anna + */ +public class PsiMethodReferenceCompatibilityConstraint implements ConstraintFormula { + private static final Logger LOG = Logger.getInstance("#" + PsiMethodReferenceCompatibilityConstraint.class.getName()); + private final PsiMethodReferenceExpression myExpression; + private final PsiType myT; + + public PsiMethodReferenceCompatibilityConstraint(PsiMethodReferenceExpression expression, PsiType t) { + myExpression = expression; + myT = t; + } + + @Override + public boolean reduce(InferenceSession session, List<ConstraintFormula> constraints) { + if (LambdaHighlightingUtil.checkInterfaceFunctional(myT) != null) { + return false; + } + + final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(myT); + if (interfaceMethod == null) { + return false; + } + + final PsiSubstitutor substitutor = LambdaUtil.getSubstitutor(interfaceMethod, PsiUtil.resolveGenericsClassInType(myT)); + final PsiParameter[] parameters = interfaceMethod.getParameterList().getParameters(); + for (PsiParameter parameter : parameters) { + if (!session.isProperType(substitutor.substitute(parameter.getType()))) { + return false; + } + } + + final PsiElement resolve = myExpression.resolve(); + if (resolve == null) { + return false; + } + + final PsiType returnType = interfaceMethod.getReturnType(); + LOG.assertTrue(returnType != null, interfaceMethod); + if (PsiType.VOID.equals(returnType)) { + return true; + } + + if (resolve instanceof PsiMethod) { + final PsiMethod method = (PsiMethod)resolve; + final PsiType referencedMethodReturnType; + if (method.isConstructor()) { + final PsiClass containingClass = method.getContainingClass(); + LOG.assertTrue(containingClass != null, method); + referencedMethodReturnType = JavaPsiFacade.getElementFactory(method.getProject()).createType(containingClass); + } + else { + referencedMethodReturnType = method.getReturnType(); + } + LOG.assertTrue(referencedMethodReturnType != null, method); + + if (myExpression.getTypeParameters().length == 0 && + ((PsiMethod)resolve).getTypeParameters().length > 0 && + PsiPolyExpressionUtil.mentionsTypeParameters(returnType, new HashSet<PsiTypeParameter>(Arrays.asList(interfaceMethod.getTypeParameters())))) { + //todo target type constraint + return true; + } + + if (PsiType.VOID.equals(referencedMethodReturnType)) { + return false; + } + + constraints.add(new TypeCompatibilityConstraint(substitutor.substitute(returnType), referencedMethodReturnType)); + } + + return true; + } +} 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 64c28d1b462f..e2677bf7a6b3 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 @@ -20,7 +20,6 @@ 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 org.jetbrains.annotations.NotNull; import java.util.List; @@ -39,7 +38,7 @@ public class SubtypingConstraint implements ConstraintFormula { } @Override - public boolean reduce(InferenceSession session, List<ConstraintFormula> constraints, List<ConstraintFormula> delayedConstraints) { + public boolean reduce(InferenceSession session, List<ConstraintFormula> constraints) { if (myIsRefTypes) { if (session.isProperType(myS) && session.isProperType(myT)) { if (myT == null || myS == null) return myS == myT; @@ -127,6 +126,11 @@ public class SubtypingConstraint implements ConstraintFormula { } return false; } else { + + if (myS instanceof PsiCapturedWildcardType) { + myS = ((PsiCapturedWildcardType)myS).getWildcard(); + } + if (myS instanceof PsiWildcardType) { final PsiType sBound = ((PsiWildcardType)myS).getBound(); if (sBound != null && ((PsiWildcardType)myS).isSuper()) { @@ -140,9 +144,19 @@ public class SubtypingConstraint implements ConstraintFormula { } return false; } else { + InferenceVariable inferenceVariable = session.getInferenceVariable(myT); if (myS instanceof PsiWildcardType) { - return false; + return inferenceVariable != null && inferenceVariable.isCaptured(); } else { + if (inferenceVariable != null) { + inferenceVariable.addBound(myS, InferenceBound.EQ); + return true; + } + inferenceVariable = session.getInferenceVariable(myS); + if (inferenceVariable != null) { + inferenceVariable.addBound(myT, InferenceBound.EQ); + return true; + } constraints.add(new SubtypingConstraint(myT, myS, true)); return true; } @@ -159,6 +173,9 @@ public class SubtypingConstraint implements ConstraintFormula { SubtypingConstraint that = (SubtypingConstraint)o; if (myIsRefTypes != that.myIsRefTypes) return false; + + if (!myIsRefTypes && 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; 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 353f03b66a80..cd9ec95f1d0d 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 @@ -37,7 +37,7 @@ public class TypeCompatibilityConstraint implements ConstraintFormula { } @Override - public boolean reduce(InferenceSession session, List<ConstraintFormula> constraints, List<ConstraintFormula> delayedConstraints) { + public boolean reduce(InferenceSession session, List<ConstraintFormula> constraints) { if (session.isProperType(myT) && session.isProperType(myS)) { return TypeConversionUtil.isAssignable(myS, 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 a71465653a6f..06e7b2b101ad 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 @@ -38,7 +38,7 @@ public class TypeEqualityConstraint implements ConstraintFormula { } @Override - public boolean reduce(InferenceSession session, List<ConstraintFormula> constraints, List<ConstraintFormula> delayedConstraints) { + public boolean reduce(InferenceSession session, List<ConstraintFormula> constraints) { if (session.isProperType(myT) && session.isProperType(myS)) { return myT.equals(myS); } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiArrayInitializerExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiArrayInitializerExpressionImpl.java index 4e2300fcf687..80b7e94f972b 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiArrayInitializerExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiArrayInitializerExpressionImpl.java @@ -18,24 +18,23 @@ package com.intellij.psi.impl.source.tree.java; import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.*; -import com.intellij.psi.impl.source.Constants; import com.intellij.psi.impl.source.tree.*; -import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.ChildRoleBase; +import com.intellij.psi.tree.IElementType; import com.intellij.util.CharTable; import org.jetbrains.annotations.NotNull; -public class PsiArrayInitializerExpressionImpl extends ExpressionPsiElement implements PsiArrayInitializerExpression, Constants { +public class PsiArrayInitializerExpressionImpl extends ExpressionPsiElement implements PsiArrayInitializerExpression { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.PsiArrayInitializerExpressionImpl"); public PsiArrayInitializerExpressionImpl() { - super(ARRAY_INITIALIZER_EXPRESSION); + super(JavaElementType.ARRAY_INITIALIZER_EXPRESSION); } @Override @NotNull public PsiExpression[] getInitializers(){ - return getChildrenAsPsiElements(EXPRESSION_BIT_SET, PsiExpression.ARRAY_FACTORY); + return getChildrenAsPsiElements(ElementType.EXPRESSION_BIT_SET, PsiExpression.ARRAY_FACTORY); } @Override @@ -69,10 +68,10 @@ public class PsiArrayInitializerExpressionImpl extends ExpressionPsiElement impl return null; case ChildRole.LBRACE: - return findChildByType(LBRACE); + return findChildByType(JavaTokenType.LBRACE); case ChildRole.RBRACE: - return findChildByType(RBRACE); + return findChildByType(JavaTokenType.RBRACE); } } @@ -80,17 +79,17 @@ public class PsiArrayInitializerExpressionImpl extends ExpressionPsiElement impl public int getChildRole(ASTNode child) { LOG.assertTrue(child.getTreeParent() == this); IElementType i = child.getElementType(); - if (i == COMMA) { + if (i == JavaTokenType.COMMA) { return ChildRole.COMMA; } - else if (i == LBRACE) { + else if (i == JavaTokenType.LBRACE) { return ChildRole.LBRACE; } - else if (i == RBRACE) { + else if (i == JavaTokenType.RBRACE) { return ChildRole.RBRACE; } else { - if (EXPRESSION_BIT_SET.contains(child.getElementType())) { + if (ElementType.EXPRESSION_BIT_SET.contains(child.getElementType())) { return ChildRole.EXPRESSION_IN_LIST; } return ChildRoleBase.NONE; @@ -129,17 +128,17 @@ public class PsiArrayInitializerExpressionImpl extends ExpressionPsiElement impl if (ElementType.EXPRESSION_BIT_SET.contains(first.getElementType())) { final CharTable charTab = SharedImplUtil.findCharTableByTree(this); for (ASTNode child = first.getTreeNext(); child != null; child = child.getTreeNext()) { - if (child.getElementType() == COMMA) break; + if (child.getElementType() == JavaTokenType.COMMA) break; if (ElementType.EXPRESSION_BIT_SET.contains(child.getElementType())) { - TreeElement comma = Factory.createSingleLeafElement(COMMA, ",", 0, 1, charTab, getManager()); + TreeElement comma = Factory.createSingleLeafElement(JavaTokenType.COMMA, ",", 0, 1, charTab, getManager()); super.addInternal(comma, comma, first, Boolean.FALSE); break; } } for (ASTNode child = first.getTreePrev(); child != null; child = child.getTreePrev()) { - if (child.getElementType() == COMMA) break; + if (child.getElementType() == JavaTokenType.COMMA) break; if (ElementType.EXPRESSION_BIT_SET.contains(child.getElementType())) { - TreeElement comma = Factory.createSingleLeafElement(COMMA, ",", 0, 1, charTab, getManager()); + TreeElement comma = Factory.createSingleLeafElement(JavaTokenType.COMMA, ",", 0, 1, charTab, getManager()); super.addInternal(comma, comma, child, Boolean.FALSE); break; } 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 3093099e228a..5091ea053471 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 @@ -19,6 +19,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.*; import com.intellij.psi.controlFlow.*; import com.intellij.psi.impl.PsiImplUtil; +import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil; import com.intellij.psi.impl.source.tree.ChildRole; import com.intellij.psi.impl.source.tree.JavaElementType; import com.intellij.psi.scope.PsiScopeProcessor; @@ -63,7 +64,7 @@ public class PsiLambdaExpressionImpl extends ExpressionPsiElement implements Psi @Nullable @Override public PsiType getFunctionalInterfaceType() { - return LambdaUtil.getFunctionalInterfaceType(this, true); + return FunctionalInterfaceParameterizationUtil.getFunctionalType(LambdaUtil.getFunctionalInterfaceType(this, true), this); } @Override @@ -118,6 +119,6 @@ public class PsiLambdaExpressionImpl extends ExpressionPsiElement implements Psi for (PsiParameter parameter : parameters) { if (parameter.getTypeElement() == null) return false; } - return parameters.length > 0; + return true; } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodCallExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodCallExpressionImpl.java index 1dd74f133dcf..36013c3625a3 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodCallExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodCallExpressionImpl.java @@ -170,7 +170,7 @@ public class PsiMethodCallExpressionImpl extends ExpressionPsiElement implements } @Nullable - private static PsiType getResultType(PsiExpression call, + private static PsiType getResultType(PsiMethodCallExpression call, PsiReferenceExpression methodExpression, JavaResolveResult result, @NotNull final LanguageLevel languageLevel) { @@ -196,40 +196,46 @@ public class PsiMethodCallExpressionImpl extends ExpressionPsiElement implements ret = ((PsiClassType)ret).setLanguageLevel(languageLevel); } if (is15OrHigher) { - final PsiSubstitutor substitutor = result.getSubstitutor(); - PsiType substitutedReturnType = substitutor.substitute(ret); - if (substitutedReturnType == null) return TypeConversionUtil.erasure(ret); - if (PsiUtil.isRawSubstitutor(method, substitutor)) { - final PsiType returnTypeErasure = TypeConversionUtil.erasure(ret); - if (Comparing.equal(TypeConversionUtil.erasure(substitutedReturnType), returnTypeErasure)) { - return returnTypeErasure; - } - } - PsiType lowerBound = PsiType.NULL; - if (substitutedReturnType instanceof PsiCapturedWildcardType) { - lowerBound = ((PsiCapturedWildcardType)substitutedReturnType).getLowerBound(); - } else if (substitutedReturnType instanceof PsiWildcardType) { - lowerBound = ((PsiWildcardType)substitutedReturnType).getSuperBound(); - } - if (lowerBound != PsiType.NULL) { //? super - final PsiClass containingClass = method.getContainingClass(); - final PsiExpression qualifierExpression = methodExpression.getQualifierExpression(); - final PsiClass childClass = qualifierExpression != null ? PsiUtil.resolveClassInClassTypeOnly(qualifierExpression.getType()) : null; - if (containingClass != null && childClass != null) { - final PsiType typeInChildClassTypeParams = TypeConversionUtil.getSuperClassSubstitutor(containingClass, childClass, PsiSubstitutor.EMPTY).substitute(ret); - final PsiClass substituted = PsiUtil.resolveClassInClassTypeOnly(typeInChildClassTypeParams); - if (substituted instanceof PsiTypeParameter) { - final PsiClassType[] extendsListTypes = substituted.getExtendsListTypes(); - if (extendsListTypes.length == 1) { - return extendsListTypes[0]; - } - } + return captureReturnType(call, method, ret, result.getSubstitutor()); + } + return TypeConversionUtil.erasure(ret); + } + } + + public static PsiType captureReturnType(PsiMethodCallExpression call, + PsiMethod method, + PsiType ret, + PsiSubstitutor substitutor) { + PsiType substitutedReturnType = substitutor.substitute(ret); + if (substitutedReturnType == null) return TypeConversionUtil.erasure(ret); + if (PsiUtil.isRawSubstitutor(method, substitutor)) { + final PsiType returnTypeErasure = TypeConversionUtil.erasure(ret); + if (Comparing.equal(TypeConversionUtil.erasure(substitutedReturnType), returnTypeErasure)) { + return returnTypeErasure; + } + } + PsiType lowerBound = PsiType.NULL; + if (substitutedReturnType instanceof PsiCapturedWildcardType) { + lowerBound = ((PsiCapturedWildcardType)substitutedReturnType).getLowerBound(); + } else if (substitutedReturnType instanceof PsiWildcardType) { + lowerBound = ((PsiWildcardType)substitutedReturnType).getSuperBound(); + } + if (lowerBound != PsiType.NULL) { //? super + final PsiClass containingClass = method.getContainingClass(); + final PsiExpression qualifierExpression = call.getMethodExpression().getQualifierExpression(); + final PsiClass childClass = qualifierExpression != null ? PsiUtil.resolveClassInClassTypeOnly(qualifierExpression.getType()) : null; + if (containingClass != null && childClass != null) { + final PsiType typeInChildClassTypeParams = TypeConversionUtil.getSuperClassSubstitutor(containingClass, childClass, PsiSubstitutor.EMPTY).substitute(ret); + final PsiClass substituted = PsiUtil.resolveClassInClassTypeOnly(typeInChildClassTypeParams); + if (substituted instanceof PsiTypeParameter) { + final PsiClassType[] extendsListTypes = substituted.getExtendsListTypes(); + if (extendsListTypes.length == 1) { + return extendsListTypes[0]; } } - return PsiImplUtil.normalizeWildcardTypeByPosition(substitutedReturnType, call); } - return TypeConversionUtil.erasure(ret); } + return PsiImplUtil.normalizeWildcardTypeByPosition(substitutedReturnType, call); } } 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 46788578dee6..537ce23c3a77 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 @@ -72,6 +72,15 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase } @Override + public boolean isExact() { + PsiElement resolve = resolve(); + if (resolve instanceof PsiMethod) { + return !((PsiMethod)resolve).isVarArgs(); + } + return true; + } + + @Override public PsiExpression getQualifierExpression() { final PsiElement qualifier = getQualifier(); return qualifier instanceof PsiExpression ? (PsiExpression)qualifier : null; 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 27e4227b5afb..6992e9f5796e 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 @@ -51,15 +51,15 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ private static final Logger LOG = Logger.getInstance("#com.intellij.psi.scope.conflictResolvers.JavaMethodsConflictResolver"); private final PsiElement myArgumentsList; - private final PsiType[] myActualParameterTypes; + private PsiType[] myActualParameterTypes; protected LanguageLevel myLanguageLevel; public JavaMethodsConflictResolver(@NotNull PsiExpressionList list, @NotNull LanguageLevel languageLevel) { - this(list, list.getExpressionTypes(), languageLevel); + this(list, null, languageLevel); } public JavaMethodsConflictResolver(@NotNull PsiElement argumentsList, - @NotNull PsiType[] actualParameterTypes, + PsiType[] actualParameterTypes, @NotNull LanguageLevel languageLevel) { myArgumentsList = argumentsList; myActualParameterTypes = actualParameterTypes; @@ -71,7 +71,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ if (conflicts.isEmpty()) return null; if (conflicts.size() == 1) return conflicts.get(0); - boolean atLeastOneMatch = checkParametersNumber(conflicts, myActualParameterTypes.length, true); + boolean atLeastOneMatch = checkParametersNumber(conflicts, getActualParameterTypes().length, true); if (conflicts.size() == 1) return conflicts.get(0); checkSameSignatures(conflicts); @@ -80,7 +80,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ checkAccessStaticLevels(conflicts, true); if (conflicts.size() == 1) return conflicts.get(0); - checkParametersNumber(conflicts, myActualParameterTypes.length, false); + checkParametersNumber(conflicts, getActualParameterTypes().length, false); if (conflicts.size() == 1) return conflicts.get(0); final int applicabilityLevel = checkApplicability(conflicts); @@ -96,7 +96,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ checkSpecifics(conflicts, applicabilityLevel, myLanguageLevel); if (conflicts.size() == 1) return conflicts.get(0); - checkPrimitiveVarargs(conflicts, myActualParameterTypes.length); + checkPrimitiveVarargs(conflicts, getActualParameterTypes().length); if (conflicts.size() == 1) return conflicts.get(0); checkAccessStaticLevels(conflicts, false); @@ -109,8 +109,8 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ private void checkLambdaApplicable(@NotNull List<CandidateInfo> conflicts, @NotNull LanguageLevel languageLevel) { if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_8)) return; - for (int i = 0; i < myActualParameterTypes.length; i++) { - PsiType parameterType = myActualParameterTypes[i]; + for (int i = 0; i < getActualParameterTypes().length; i++) { + PsiType parameterType = getActualParameterTypes()[i]; if (parameterType instanceof PsiLambdaExpressionType) { final PsiLambdaExpression lambdaExpression = ((PsiLambdaExpressionType)parameterType).getExpression(); for (Iterator<CandidateInfo> iterator = conflicts.iterator(); iterator.hasNext(); ) { @@ -122,7 +122,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ 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), true)) { + if (!LambdaUtil.isAcceptable(lambdaExpression, conflict.getSubstitutor().substitute(paramType), lambdaExpression.hasFormalParameterTypes())) { iterator.remove(); } else { /*todo @@ -141,7 +141,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ } } } - checkMoreSpecificReturnType(conflicts, myActualParameterTypes, languageLevel); + checkMoreSpecificReturnType(conflicts, getActualParameterTypes(), languageLevel); } public void checkSpecifics(@NotNull List<CandidateInfo> conflicts, @@ -426,6 +426,14 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ (method.getCurrentFileResolveScope() instanceof PsiImportStaticStatement ? 0 : 1); } + private PsiType[] getActualParameterTypes() { + if (myActualParameterTypes == null) { + LOG.assertTrue(myArgumentsList instanceof PsiExpressionList, myArgumentsList); + myActualParameterTypes = ((PsiExpressionList)myArgumentsList).getExpressionTypes(); + } + return myActualParameterTypes; + } + private enum Specifics { FIRST, SECOND, @@ -489,7 +497,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ ProgressManager.checkCanceled(); PsiType type1 = classSubstitutor1.substitute(types1[i]); PsiType type2 = classSubstitutor2.substitute(types2[i]); - PsiType argType = i < myActualParameterTypes.length ? myActualParameterTypes[i] : null; + PsiType argType = i < getActualParameterTypes().length ? getActualParameterTypes()[i] : null; boolean boxingInFirst = false; if (isBoxingHappened(argType, type1, languageLevel)) { @@ -691,6 +699,12 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ for (int functionalInterfaceIdx = 0; functionalInterfaceIdx < actualParameterTypes.length; functionalInterfaceIdx++) { final PsiType interfaceReturnType = getReturnType(functionalInterfaceIdx, method); final PsiType interfaceReturnType1 = getReturnType(functionalInterfaceIdx, conflict); + if (actualParameterTypes[functionalInterfaceIdx] instanceof PsiLambdaExpressionType) { + final PsiLambdaExpression lambdaExpression = ((PsiLambdaExpressionType)actualParameterTypes[functionalInterfaceIdx]).getExpression(); + if (!lambdaExpression.hasFormalParameterTypes()) { + return Specifics.NEITHER; + } + } if (actualParameterTypes[functionalInterfaceIdx] instanceof PsiLambdaExpressionType || actualParameterTypes[functionalInterfaceIdx] instanceof PsiMethodReferenceType) { if (interfaceReturnType != null && interfaceReturnType1 != null && !Comparing.equal(interfaceReturnType, interfaceReturnType1)) { Specifics moreSpecific1 = comparePrimitives(actualParameterTypes[functionalInterfaceIdx], interfaceReturnType, interfaceReturnType1); |