diff options
author | Tor Norbye <tnorbye@google.com> | 2014-04-25 07:38:52 -0700 |
---|---|---|
committer | Tor Norbye <tnorbye@google.com> | 2014-04-25 07:38:58 -0700 |
commit | 0f831a730c50607e2ffd95020875af6185e17734 (patch) | |
tree | 3caf947bbfceeb37eda9c4a1bee319fdd7678fe5 /java/java-impl/src/com/intellij | |
parent | 92584642bab4fdb27ac1067c124f4636be762978 (diff) | |
download | idea-0f831a730c50607e2ffd95020875af6185e17734.tar.gz |
Snapshot idea/136.1761 from git://git.jetbrains.org/idea/community.git
3608216: Merge remote-tracking branch 'origin/master'
0d16248: Django inspection HTMLs moved to appropriate place
1ed8715: PY-1194 Provide completion and navigation for url tag in django template Inspection added.
4c6ec52: Naive fix for EA-53569
44c2a03: Do not wrap border with TitledBorder if there is not title
8591130: omg2 [r=ignatov]
dce57e7: omg
3b164b9: Merge remote-tracking branch 'origin/master'
9c04fe7: Ctrl-Q: process java 8 signature style as 1.8 javadoc could also be run on sources 1.6 (IDEA-124175)
b073132: javadoc: ensure that generic arguments are shown in error presentation
b8fb550: IDEA-124271
209d176: disable stream api conversion on iterable (IDEA-124222)
6ca89eb: default external javadoc url for java 8 fixed (IDEA-124175)
2fe28f0: Merge remote-tracking branch 'origin/master'
f65712c: Merge remote-tracking branch 'origin/master'
7de60e2f: Don't escape spaces as it brakes mappings and they are escaped later in GeneralCommandLine (PY-12550).
2bd67bc: IDEA-90194 Ability to disable drag & drop in Project View
f772fb2: Merge remote-tracking branch 'origin/master'
817908d: fixed importing for the iron python
053b716: Merge remote-tracking branch 'origin/master'
1d04dc7: fixed unittest folder tests
76f35f3: suppress doCancelAction
0d9b47d: IDEA-124260 Data Sources and Drivers: can't apply changes to schemas that are shown and used to resolve
f72e4f5: testdata for IDEA-124148
1c431a8: create meth reference from usage: substitute param types (IDEA-124322)
c160fc5: copy to temp/array for non-effectively final variables used in lambda expressions
265f0dc: lambda -> anonymous: static calls (IDEA-124187)
2200bba: method hierarchy: search functional expressions by current method only (IDEA-124320); navigation (IDEA-124319)
54ced00: highlight all pairs of methods with same erasures (IDEA-124116)
f3efd90: IDEA-120865 jre7 osx fullscreen: "space" is not freed when project is closed
6924cc4: IDEA-118062 Gradle Run Configuration: 'working directory' is set incorrectly
09333b1: External system: source package prefix support added; fix for out-of-process mode support
6de52dc: Gradle: update Tooling API version up to 1.12-rc-1, fix classpath for out-of-process mode
4ff20d5: InconsistentResourceBundle test fixed
90bb5ab: IDEA-124301 jdk9 builds cannot be used for project/module compilation
1236318: always go to file if nothing found
43f40bf: Merge remote-tracking branch 'origin/master'
b2d0942: Add default mapping to /vagrant only in case of absent mappings in Vagrantfile (PY-12700).
fc31680: IDEA-124290
773f103: Offer to launch Vagrant if it is down on getting ssh-config (PY-12672).
460ef41: DumbService.smartInvokeLater(...)
577579d: cleanup after extracting java postfix template provider
214f99b: IDEA-103836
a41e7d8: Merge remote-tracking branch 'origin/master'
4076596: fixed memory leak
c5207b2: fixed PY-12543 Project Interpreters: too big or too small details popup
40d91f5: IDEA-63106 new inspections added to InconsistentResourceBundleInspection
4bc9f42: fixed PY-12690 Detected from creating virtualenv interpreter has invalid slashes
e6d8c98: extract right arrow
43b861b: don't use borders and insets in output html/rtf (IDEA-67767)
6c4dbea: use service instead of application component (IDEA-67767)
aa6fb9f: remove 'Strip common indent' setting from UI (IDEA-67767)
5651ab5: IDEA-123775 (String.equals("") inspection fixes code incorrectly)
c1d9f5f: fixed PY-12696 Create VirtualEnv: when adding first base interpreter it is not selected right away
482491a: Platform: Local History can survive for more than 30 days now (int overflow fixed)
a0125dc: Platform: always allow writing module files (IDEA-123899)
3a294e9: removed unused component methods
7cc124e: optimisation: avoid containingfile calculation
06f574a: readable toString()
60f2a36: perforce tests fixed
46fea0f: fewer create/delete operations
7269bce: drain file type detection queue in tests
d0c6ef5: cleanup
9df7136: Gradle: installer build fix
152c230: Platform: Local History can survive for more than 30 days now
f5e7215: do not rely on memory index storage isBufferedFlag to process physical file contents
ebe62cf: customize password field labels
97ade8d: ability to enable only visible components
3541938: introduce beforeOKAction()
13bf7e1: cleanup
4a12b1f: junit: workaround for old junit versions (IDEA-124201)
21003e0: Merge remote-tracking branch 'origin/master'
c2067ff: PY-1194 Provide completion and navigation for url tag in django template PY-3591 Support {% url %} tag arguments completion
5f295fe: do not cancel offline inspections
2b8e2e8: add unchecked warning calls also for method references
57e886f: testdata: check that method ref on static interface method is accepted
8bad807: lambda: do not skip generic method when non-generic method exist in the same class
7d74b9d: NPE
0da9f91: testdata: ensure overload resolution prefer correct one from methods with boxed types
2c49817: NPE
d5107d6: testdata: ensure intersection type is not missed during inference
7898108: testdata: ensure lambda can't be inferred from type parameter
5b91054: testdata: ensure overload resolution by return type should not take place for interrupted control flow
9aa2f3a: testdata: ensure correct parameters number in functional interface method
1698f7b: testdata: ensure method ref qualified are checked over static problems
b49d8e75: testdata
f1f6fcf: functional interfaces: ignore methods with type parameters during abstract method choosing
a55db18: lambda: accept intersection type when exactly one conjunct is functional
4a34bd5: do not report unrelated return type error only for generics methods
76a9293: testdata
17b020f: new overload resolution: covariant comparison of return types
98ab76f: new overload resolution: most specific check on invalid class exceptions fixed
552dfe9: lambda: intersection type produces conjunction of abstract methods
bd9dbfc: testdata
9914757: warn about underscore identifier
72ae579: IDEA-109187 new HgReference validator implemented
d86307e: tip reference moved as a separated static constant to HgUtil
71cd276: Fix scrolling in module aware configurables [r=ushakov]
37ed33e: Missed commit for IDEA-79312
da52f84: IDEA-79312 text cursor gets lost - could bee disabled by focus.fix.lost.cursor key
a39b289: [git log] IDEA-122305 Fix structure filter.
339dd23: beforeShown() & preselect laf-default editor scheme 2
f9d8704: PY-1194 Provide completion and navigation for url tag in django template PY-3591 Support {% url %} tag arguments completion
17e8b30: ctrl+delete/ctrl+backspace enhancements IDEA-100906 Ruby-Editor: CTRL+BACKSPACE Could Not Delete A String
a95fd00: remove copyright messages
bf06d9d: read-action for getFilesForFastWordSearch
cdcd770: IDEA-123687 Velocity formatter inserts wrong linebreak
562443f: Fixed WI-17474 Custom Folding: defaultstate="collapsed" does not seem to have any effect (the node itself is already a line comment)
d86998d: Cleanup warnings
4bbd22c: jb v8 debug protocol: evaluate
46eaf0b: NPE
4101b8c: cleanup
399e745: write action required
004dfc4: IDEA-124220 Auto-popup parameter info should work after smart completion which inserted a comma
0bd06e5: More on comparison that is always false due to being out of type range on implicit type conversion (IDEA-124210)
b6bccb7: AppCode: minimum OS X version specified in .app
ca8a657: add aliases for Lafs
e254ebf: Merge branch 'master' of git.labs.intellij.net:idea/community
5c594f6: Gradle: update Tooling API version up to 1.12-rc-1
17fcca3: Merge remote-tracking branch 'origin/master'
5248eb0: IDEA-119996 FilePathImpl: avoid VFS refresh from getVirtualFile etc.
9c69111: [vcs] Reuse the VirtualFile instead of creating FilePathImpl on File
c08f50b: fixed EA-54835 - NPE: PythonNoseTestConfigurationProducer.isAvailable
d627711: fixed EA-55749 - AIOOBE: PyStructuredDocstringFormatter.formatDocstring
c9a1c11: apply laf once, fix stale bg, add beforeShown() & preselect laf-default editor scheme
3e576c2: fixed EA-55872 - NPE: PyProtectedMemberInspection$Visitor.checkReference
147c647: use ValueType enum instead of plain numbers
2e517c5: IDEA-112050 vcs: fix ByteBuffer to array conversion
97a6a21: possible race condition fixed
cb20ef5: Prevent horizontal scrollbar appearance if an error message is too long
cbb86d4: IDEA-124021 Cannot resolve method 'print(int)' with JSP custom tags: comment
362b4d7: IDEA-123986 New project wizard: remove highlighting from disabled templates
cc57b39: do not include runtime dependencies to compilation scope (ZD-25927)
7ac3c11: paste rich-text data: NPE fixed
89ca157: Extract Java live postfix templates provider
e5eb7aa: EA-31437 - assert: DocumentFoldingInfo.writeExternal
e2461d5: use JBImageIcon
e9eb171: initial
ed33f35: fix Keymap page on Mac/Darcula. see same in LafManager for more info.
99bc2e9: open some API
d9aed3f: process class names just once in completion
094f040: IDEA-122362 'getClass()' should be suggested in smart completion if Class<? extends SomeAncestorOfCurrentClass> is expected
1a34573: IDEA-120139 Autopopup doesn't popup sometimes after completion
e8c981a: create LookupUi and move there some ui-related code from LookupImpl; skip this code in tests
89d771e: @NotNull
8d25ba3: Merge remote-tracking branch 'origin/master'
7fcce27: fix darcula lafinfo
bfef59e: Start plugins wizard #19 usability improvements
5cbd491: minor fix
58d2f15: fix bg
40fa260: don't create content entry for temp directory of temp project when opening single file
e31a4c1: Correctly handle custom folding "desc" attribute followed by "defaultstate"
448e9f8: don't report on incomplete code or comparisons that are already reported by "Constant conditions & exceptions"
6e68111: remove superfluous inspection
a2cc5ba: expand description
814378f: Gradle: gradle distribution pattern updated
e9485f0: use TransparentPanel
db66426: initial
a712571: suppress unused params inspection
640ddf3: make labels have constant height to avoid relayout and blinking
921f39e: don't fill bg if component is not opaque
a43d7f8: added new test for live postfix templates
50addd3: IDEA-123935 New Project wizard: no project/global libraries are created on new module adding via project structure
6021da6: Merge remote-tracking branch 'origin/master'
36848a5: fixed test data
7a63d2b: Gradle: tooling extensions integration tests, avoid dependency for explicit distributions downloading in a separate run configuration (like this one http://buildserver.labs.intellij.net/viewType.html?buildTypeId=IDEATrunk_GradleDownloads)
405332a: make richCopy functionality work properly on Linux (IDEA-67767)
3dca908: some 'finally' blocks
00a4968: reverted content-dependent flag
6064460: Merge remote-tracking branch 'origin/master'
5f203cb: Fixed IDEA-124191 Code style preference : space within empty method call/declaration parentheses are not saved
0419dcc: EA-56035 - NCDFE: UnixProcessManager.<clinit>
0285ece: cleanup: use ordinary invokeLater and avoid unnecessary synchronization
0922a97: Vagrant error messaging fixed.
2676330: Save vagrant executable path to application settings (PY-12680).
947d8ab: missing test data
6154126: IDEA-124137 (Inspection: "equals() between objects of inconvertible types" should support java.util.Objects.equals() or com.google.common.base.Objects.equal())
c9fd1bb: fix name
f3ec0f7: lookup arranger tweak [zolotov, shrago] relates to IDEA-121998 SQL code completion too aggressive
c324511: fix escaping, parse decimal literals #WEB-11938 fixed
a5bcae9: Github: fix error message
95d057d: Github: fix invalid condition
dda5341: Github: log invalid requests
d493d76: it is even better to store deltas for direct mapping values
a67ac0b: proper unpacking code
3ea5951: Properties AST factory moved to impl
c0550f7: save keys of particular snapshot before and out of index update optimistically load keys of particular snapshot before and out of index update
d6a5968: custom implementation for IdIndex inputs mapping: -20% for saving deltas
b52691e: saving / reading longs in compact variable byte format + using it for simplier code in PersistentHashMapValueStorage
0ae869e: cleanup
3222cd0: cleanup
e96aa7b: use Gray.TRANSPARENT
2861f10: use Gray.TRANSPARENT
c009821: Merge remote-tracking branch 'origin/master'
caa86fc: what a nice NPE!
3c769ac: goto popup calculations should be cancellable even after Ctrl+Space (IDEA-123714 ?)
c6fcabf: IDEA-122250 New Package: qualified name is checked against ignored directories as a whole
3af306c: IDEA-55556 Inspection suggestion: Comparison that is always false due to being out of type range on implicit type conversion
996d0c6: IDEA-123782 "Complete current statement" doesn't put colon for case branches
7a2cc54: IDEA-122383 PageUp/PageDown don't work in ShowUsages popup (Ctrl-Alt-F7)
29fec22: IDEA-123948 Constant condition and exceptions: false positive on MappedByteBuffer.getInt
0fd86de: IDEA-122946 final modifier not inserted when completing a sequence of parameters from an inner method IDEA-123493 Smart completion makes completed variable final
019a68b: IDEA-123289 Infer nullability of 'for each' variable from type annotations of the collection parameter
c18c4ff: IDEA-120964 Make it more obvious that background compiler is disabled in power save mode
dc2f64a: use superclass for inner class variable name suggestion (IDEA-122109)
c47713f: prefer T if Class<? extends T> is expected (IDEA-121339)
c960901: OC-9559 IDEA-107592
64fc873: cleanup
c159a1a: Start plugins wizard #17
043fa14: extra assert
7eac40c: larger btree block size / load factor increased for better space utilization
a4598a1: enable snapshot mapping
e80c2b3: trigram index enabled in internal mode
527f139: delta encoding of file id set to decrease output size ~3x
a47785b: move to MnemonicHelper
5b12f32: cleanup
27ef5f4: bg progresses for presentation mode
656e311: add transparent color
ddce960: EA-55788 - assert: GitRepositoryImpl
dfc2ef7: external-system: project import fixed to use correct fileToImport
675d14e: OC-9559 IDEA-107592
e6d5ea6: IDEA-86665 hg annotate: ignore whitespace changes
6e551ba: test hg executor updated with ignoreNonZeroExitCode addition option
8798162d: cleanup
45f98c5: IDEA-124021 Cannot resolve method 'print(int)' with JSP custom tags
67f1d44: Better fix for IDEA-124096 open commit actions popup on ctrl+alt+P
8aab4ce: IDEA-123691 Minor project wizard edits: moving settings to the first page
9cb1c40: IDEA-122845 Try to fetch issues, if resource with information about user is not available in this version of Redmine
a2c9393: Add key to JiraRepository to enable old behavior where credentials were sent with every request via basic auth
ce17994: Add special type of exception to indicate request failure from response handlers and other callbacks. ResponseHandler has option to suppress exceptions, if requested resource was not found.
de0f3df: notnull, toString
10c30e2: IDEA-123886, dropped UTF guessing setting
bf14e11: remove obsolete cruft
7b15687: notnull
c82fb9d: mem leak
de48566: test
8a9b3d0: doc leak
d163e52: comment
1274dba: removed confusing createTempPath()
057c5f9: do not expand usage tree if there are too many nodes
e7f245f: debugging IDEA-120167 Phantom eternal Ant task on make
6bf1671: Merge remote-tracking branch 'origin/master'
be70ee8: PY-2880: Django: provide completion for context_object_name value in django template * test added * fixture:complete() is reenterable now
1a99a14: Start plugins wizard #16 and it works
30f6e0e: fix false positive with smart tabs
76fcb91: use provided value description instead of just classname don't compute object presentation by custom configured properties if value description is not equals to class name
014c0e3: jb v8 debug protocol: load full string value
223f19a: typo
339e7d6: WEB-11834 IIS ACL Permissions when creating foundation/bootstrap projects from templates
b875e62: remove freemarker leftovers from html lexer #WEB-11907 fixed
b84c236: push language levels synchronously for non-refresh vfs events (IDEA-123876)
a32e2eb: code style
a593533: Github: mark invalid password as invalid
10d5070: [git] IDEA-124081 implement IDEA-98189 for clone
a9fa3a2: IDEA-124096 open commit actions popup on ctrl+alt+P
83bc60b: AppCode: Xcode keymap tunes for tool windows +review CR-IC-5162
c976200: Merge remote-tracking branch 'origin/master'
48d5f8c: Refactoring: getImportSourceQName() is used
d324bc0: GeneratedFolder icon
5d90886: Add "try-with-resources" live postfix template
cfec5b0: cleanup
e587000: Platform: bug-typo in DnDSupport
814a79a: Unify prefix calculation rules for live templates
f447531: IDEA-124005 Reading resources out of a source directory doesn't make it a resource directory
Change-Id: Ie2989b1157ae12b92c48d9556db64999ea68e83e
Diffstat (limited to 'java/java-impl/src/com/intellij')
56 files changed, 894 insertions, 379 deletions
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java b/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java index a5431b56082a..270d6f93f767 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java @@ -22,20 +22,20 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; +import com.intellij.psi.impl.search.AllClassesSearchExecutor; import com.intellij.psi.impl.source.PostprocessReformattingAspect; import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl; import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.search.searches.AllClassesSearch; import com.intellij.util.Consumer; import com.intellij.util.IncorrectOperationException; import com.intellij.util.Processor; import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; +import java.util.LinkedHashSet; import java.util.Set; /** @@ -184,18 +184,17 @@ public class AllClassesGetter { @NotNull Project project, @NotNull GlobalSearchScope scope, @NotNull Processor<PsiClass> processor) { - AllClassesSearch.search(scope, project, new Condition<String>() { + final Set<String> names = new THashSet<String>(10000); + AllClassesSearchExecutor.processClassNames(project, scope, new Consumer<String>() { @Override - public boolean value(String s) { - return prefixMatcher.isStartMatch(s); - } - }).forEach(processor); - AllClassesSearch.search(scope, project, new Condition<String>() { - @Override - public boolean value(String s) { - return prefixMatcher.prefixMatches(s); + public void consume(String s) { + if (prefixMatcher.prefixMatches(s)) { + names.add(s); + } } - }).forEach(processor); + }); + LinkedHashSet<String> sorted = CompletionUtil.sortMatching(prefixMatcher, names); + AllClassesSearchExecutor.processClassesByNames(project, scope, sorted, processor); } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java index d64529008ca4..28767e6ce422 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -400,7 +400,7 @@ public class JavaCompletionContributor extends CompletionContributor { if (((PsiJavaCodeReferenceElement)parent).getQualifier() != null) return isSecondCompletion; if (parent instanceof PsiJavaCodeReferenceElementImpl && - ((PsiJavaCodeReferenceElementImpl)parent).getKind() == PsiJavaCodeReferenceElementImpl.PACKAGE_NAME_KIND) { + ((PsiJavaCodeReferenceElementImpl)parent).getKind(parent.getContainingFile()) == PsiJavaCodeReferenceElementImpl.PACKAGE_NAME_KIND) { return false; } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java index b66073e2f6f0..d144a67fcb69 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java @@ -34,6 +34,7 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.Function; +import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; @@ -425,20 +426,35 @@ public class JavaCompletionSorting { } private static class PreferExpected extends LookupElementWeigher { - private final boolean myAcceptClasses; + private final boolean myConstructorPossible; private final ExpectedTypeInfo[] myExpectedTypes; + private final List<PsiType> myExpectedClasses = new SmartList<PsiType>(); - public PreferExpected(boolean acceptClasses, ExpectedTypeInfo[] expectedTypes) { + public PreferExpected(boolean constructorPossible, ExpectedTypeInfo[] expectedTypes) { super("expectedType"); - myAcceptClasses = acceptClasses; + myConstructorPossible = constructorPossible; myExpectedTypes = expectedTypes; + for (ExpectedTypeInfo info : expectedTypes) { + ContainerUtil.addIfNotNull(myExpectedClasses, PsiUtil.substituteTypeParameter(info.getDefaultType(), CommonClassNames.JAVA_LANG_CLASS, 0, false)); + } } @NotNull @Override - public Comparable weigh(@NotNull LookupElement item) { - return item.getObject() instanceof PsiClass && !myAcceptClasses - ? ExpectedTypeMatching.normal : getExpectedTypeMatching(item, myExpectedTypes); + public ExpectedTypeMatching weigh(@NotNull LookupElement item) { + if (item.getObject() instanceof PsiClass && !myConstructorPossible) { + PsiType itemType = JavaCompletionUtil.getLookupElementType(item); + if (itemType != null) { + for (PsiType expectedClass : myExpectedClasses) { + if (expectedClass.isAssignableFrom(itemType)) { + return ExpectedTypeMatching.expected; + } + } + } + return ExpectedTypeMatching.normal; + } + + return getExpectedTypeMatching(item, myExpectedTypes); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java index fd0de03cd792..bb0d339ffa80 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java @@ -330,7 +330,9 @@ public class JavaCompletionUtil { PsiScopesUtil.processTypeDeclarations(qualifierType, member, new MyProcessor()); - PsiType rawType = member instanceof PsiField ? ((PsiField) member).getType() : ((PsiMethod) member).getReturnType(); + PsiType rawType = member instanceof PsiField ? ((PsiField) member).getType() : + member instanceof PsiMethod ? ((PsiMethod) member).getReturnType() : + JavaPsiFacade.getElementFactory(member.getProject()).createType((PsiClass)member); return subst.get().substitute(rawType); } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java index e8c828a6c4bc..2960bd797dea 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java @@ -144,10 +144,8 @@ public class PreferByKindWeigher extends LookupElementWeigher { } } - if (myCompletionType == CompletionType.SMART) { - if (object instanceof PsiLocalVariable || object instanceof PsiParameter || object instanceof PsiThisExpression) { - return MyResult.localOrParameter; - } + if (object instanceof PsiLocalVariable || object instanceof PsiParameter || object instanceof PsiThisExpression) { + return MyResult.localOrParameter; } if (object instanceof String && item.getUserData(JavaCompletionUtil.SUPER_METHOD_PARAMETERS) == Boolean.TRUE) { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/SameSignatureCallParametersProvider.java b/java/java-impl/src/com/intellij/codeInsight/completion/SameSignatureCallParametersProvider.java index d3f0b2e62782..d898bb77ae5a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/SameSignatureCallParametersProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/SameSignatureCallParametersProvider.java @@ -19,6 +19,7 @@ import com.intellij.codeInsight.ExpectedTypesProvider; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.codeInsight.lookup.TailTypeDecorator; +import com.intellij.codeInsight.lookup.VariableLookupItem; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; @@ -72,8 +73,8 @@ class SameSignatureCallParametersProvider extends CompletionProvider<CompletionP } } - private static LookupElement createParametersLookupElement(PsiMethod takeParametersFrom, PsiElement call, PsiMethod invoked) { - PsiParameter[] parameters = takeParametersFrom.getParameterList().getParameters(); + private static LookupElement createParametersLookupElement(final PsiMethod takeParametersFrom, PsiElement call, PsiMethod invoked) { + final PsiParameter[] parameters = takeParametersFrom.getParameterList().getParameters(); final String lookupString = StringUtil.join(parameters, new Function<PsiParameter, String>() { @Override public String fun(PsiParameter psiParameter) { @@ -86,7 +87,18 @@ class SameSignatureCallParametersProvider extends CompletionProvider<CompletionP icon.setIcon(PlatformIcons.PARAMETER_ICON, 0, 2*w/5, 0); icon.setIcon(PlatformIcons.PARAMETER_ICON, 1); - final LookupElement element = LookupElementBuilder.create(lookupString).withIcon(icon); + LookupElementBuilder element = LookupElementBuilder.create(lookupString).withIcon(icon); + if (PsiTreeUtil.isAncestor(takeParametersFrom, call, true)) { + element = element.withInsertHandler(new InsertHandler<LookupElement>() { + @Override + public void handleInsert(InsertionContext context, LookupElement item) { + context.commitDocument(); + for (PsiParameter parameter : CompletionUtil.getOriginalOrSelf(takeParametersFrom).getParameterList().getParameters()) { + VariableLookupItem.makeFinalIfNeeded(context, parameter); + } + } + }); + } element.putUserData(JavaCompletionUtil.SUPER_METHOD_PARAMETERS, Boolean.TRUE); return TailTypeDecorator.withTail(element, ExpectedTypesProvider.getFinalCallParameterTailType(call, invoked.getReturnType(), invoked)); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/SmartCompletionDecorator.java b/java/java-impl/src/com/intellij/codeInsight/completion/SmartCompletionDecorator.java index e5a9ee43de69..e2cc1330f88e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/SmartCompletionDecorator.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/SmartCompletionDecorator.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInsight.completion; +import com.intellij.codeInsight.AutoPopupController; import com.intellij.codeInsight.CodeInsightSettings; import com.intellij.codeInsight.ExpectedTypeInfo; import com.intellij.codeInsight.TailType; @@ -117,8 +118,14 @@ public class SmartCompletionDecorator extends TailTypeDecorator<LookupElement> { context.commitDocument(); } myPosition = getPosition(context, this); - + + TailType tailType = computeTailType(context); + super.handleInsert(context); + + if (tailType == TailType.COMMA) { + AutoPopupController.getInstance(context.getProject()).autoPopupParameterInfo(context.getEditor(), null); + } } public static boolean hasUnboundTypeParams(final PsiMethod method, PsiType expectedType) { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java b/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java index fb7878dba26c..4e13baf779f2 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java @@ -25,6 +25,7 @@ import com.intellij.openapi.util.Key; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.filters.ElementFilter; +import com.intellij.psi.impl.light.LightMethodBuilder; import com.intellij.psi.impl.source.resolve.JavaResolveUtil; import com.intellij.psi.infos.CandidateInfo; import com.intellij.psi.scope.BaseScopeProcessor; @@ -100,14 +101,11 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme if (qualifier instanceof PsiSuperExpression) { final PsiJavaCodeReferenceElement qSuper = ((PsiSuperExpression)qualifier).getQualifier(); if (qSuper == null) { - myQualifierClass = JavaResolveUtil.getContextClass( myElement); + myQualifierClass = JavaResolveUtil.getContextClass(myElement); } else { final PsiElement target = qSuper.resolve(); myQualifierClass = target instanceof PsiClass ? (PsiClass)target : null; } - if (myQualifierClass != null) { - myQualifierType = JavaPsiFacade.getInstance(element.getProject()).getElementFactory().createType(myQualifierClass); - } } else if (qualifier != null) { setQualifierType(qualifier.getType()); @@ -117,8 +115,13 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme myQualifierClass = (PsiClass)target; } } + } else { + myQualifierClass = JavaResolveUtil.getContextClass(myElement); } } + if (myQualifierClass != null && myQualifierType == null) { + myQualifierType = JavaPsiFacade.getElementFactory(element.getProject()).createType(myQualifierClass); + } if (myOptions.checkInitialized) { myNonInitializedFields.addAll(getNonInitializedFields(element)); @@ -219,6 +222,19 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme return true; } + if (element instanceof PsiMethod) { + PsiMethod method = (PsiMethod)element; + if (PsiTypesUtil.isGetClass(method) && PsiUtil.isLanguageLevel5OrHigher(myElement)) { + PsiType patchedType = PsiTypesUtil.createJavaLangClassType(myElement, myQualifierType, false); + if (patchedType != null) { + element = new LightMethodBuilder(element.getManager(), method.getName()). + addModifier(PsiModifier.PUBLIC). + setMethodReturnType(patchedType). + setContainingClass(method.getContainingClass()); + } + } + } + if (satisfies(element, state) && isAccessible(element)) { CompletionElement element1 = new CompletionElement(element, state.get(PsiSubstitutor.KEY)); if (myResultNames.add(element1.getUniqueId())) { @@ -288,7 +304,9 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme if (!(element instanceof PsiMember)) return true; PsiMember member = (PsiMember)element; - return JavaPsiFacade.getInstance(element.getProject()).getResolveHelper().isAccessible(member, member.getModifierList(), myElement, myQualifierClass, myDeclarationHolder); + PsiClass accessObjectClass = member instanceof PsiClass ? null : myQualifierClass; + return JavaPsiFacade.getInstance(element.getProject()).getResolveHelper().isAccessible(member, member.getModifierList(), myElement, + accessObjectClass, myDeclarationHolder); } public void setCompletionElements(@NotNull Object[] elements) { diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromMethodReferenceFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromMethodReferenceFix.java index b0c29bf641e3..74df48381201 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromMethodReferenceFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromMethodReferenceFix.java @@ -124,15 +124,16 @@ public class CreateMethodFromMethodReferenceFix extends CreateFromUsageBaseFix { final PsiType interfaceReturnType = LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType); LOG.assertTrue(interfaceReturnType != null); + final PsiSubstitutor substitutor = LambdaUtil.getSubstitutor(interfaceMethod, classResolveResult); final ExpectedTypeInfo[] expectedTypes = {new ExpectedTypeInfoImpl(interfaceReturnType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, interfaceReturnType, TailType.NONE, null, ExpectedTypeInfoImpl.NULL)}; CreateMethodFromUsageFix.doCreate(targetClass, method, false, ContainerUtil.map2List(interfaceMethod.getParameterList().getParameters(), new Function<PsiParameter, Pair<PsiExpression, PsiType>>() { @Override public Pair<PsiExpression, PsiType> fun(PsiParameter parameter) { - return Pair.create(null, parameter.getType()); + return Pair.create(null, substitutor.substitute(parameter.getType())); } }), - LambdaUtil.getSubstitutor(interfaceMethod, classResolveResult), + PsiSubstitutor.EMPTY, expectedTypes, context); } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromUsageFix.java index 3ce012705c0f..b7cd8af73084 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromUsageFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromUsageFix.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,14 +17,14 @@ package com.intellij.codeInsight.daemon.impl.quickfix; import com.intellij.codeInsight.CodeInsightUtilCore; import com.intellij.codeInsight.ExpectedTypeInfo; -import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerEx; import com.intellij.codeInsight.daemon.QuickFixBundle; +import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerEx; import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.codeInsight.template.Template; import com.intellij.codeInsight.template.TemplateBuilderImpl; import com.intellij.codeInsight.template.TemplateEditingAdapter; import com.intellij.lang.annotation.HighlightSeverity; -import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; @@ -259,7 +259,7 @@ public class CreateMethodFromUsageFix extends CreateFromUsageBaseFix { startTemplate(newEditor, template, project, new TemplateEditingAdapter() { @Override public void templateFinished(Template template, boolean brokenOff) { - ApplicationManager.getApplication().runWriteAction(new Runnable() { + WriteCommandAction.runWriteCommandAction(project, new Runnable() { @Override public void run() { PsiDocumentManager.getInstance(project).commitDocument(newEditor.getDocument()); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassFix.java index 98a271629093..47ed78e48760 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassFix.java @@ -42,16 +42,16 @@ import java.util.*; public class VariableAccessFromInnerClassFix implements IntentionAction { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.quickfix.VariableAccessFromInnerClassFix"); private final PsiVariable myVariable; - private final PsiClass myClass; + private final PsiElement myContext; private final int myFixType; private static final int MAKE_FINAL = 0; private static final int MAKE_ARRAY = 1; private static final int COPY_TO_FINAL = 2; private static final Key<Map<PsiVariable,Boolean>>[] VARS = new Key[] {Key.create("VARS_TO_MAKE_FINAL"), Key.create("VARS_TO_TRANSFORM"), Key.create("???")}; - public VariableAccessFromInnerClassFix(@NotNull PsiVariable variable, @NotNull PsiClass aClass) { + public VariableAccessFromInnerClassFix(@NotNull PsiVariable variable, @NotNull PsiElement element) { myVariable = variable; - myClass = aClass; + myContext = element; myFixType = getQuickFixType(variable); if (myFixType == -1) return; @@ -87,21 +87,21 @@ public class VariableAccessFromInnerClassFix implements IntentionAction { @Override public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return myClass.isValid() && - myClass.getManager().isInProject(myClass) && + return myContext.isValid() && + myContext.getManager().isInProject(myContext) && myVariable.isValid() && myFixType != -1 && !getVariablesToFix().isEmpty() && - !inOwnInitializer(myVariable, myClass); + !inOwnInitializer(myVariable, myContext); } - private static boolean inOwnInitializer(PsiVariable variable, PsiClass aClass) { - return PsiTreeUtil.isAncestor(variable, aClass, false); + private static boolean inOwnInitializer(PsiVariable variable, PsiElement context) { + return PsiTreeUtil.isAncestor(variable, context, false); } @Override public void invoke(@NotNull Project project, Editor editor, PsiFile file) { - if (!FileModificationService.getInstance().preparePsiElementsForWrite(myClass, myVariable)) return; + if (!FileModificationService.getInstance().preparePsiElementsForWrite(myContext, myVariable)) return; try { switch (myFixType) { case MAKE_FINAL: @@ -131,8 +131,8 @@ public class VariableAccessFromInnerClassFix implements IntentionAction { @NotNull private Collection<PsiVariable> getVariablesToFix() { - Map<PsiVariable, Boolean> vars = myClass.getUserData(VARS[myFixType]); - if (vars == null) myClass.putUserData(VARS[myFixType], vars = new ConcurrentWeakHashMap<PsiVariable, Boolean>(1)); + Map<PsiVariable, Boolean> vars = myContext.getUserData(VARS[myFixType]); + if (vars == null) myContext.putUserData(VARS[myFixType], vars = new ConcurrentWeakHashMap<PsiVariable, Boolean>(1)); final Map<PsiVariable, Boolean> finalVars = vars; return new AbstractCollection<PsiVariable>() { @Override @@ -164,7 +164,7 @@ public class VariableAccessFromInnerClassFix implements IntentionAction { private void makeArray(PsiVariable variable) throws IncorrectOperationException { PsiType type = variable.getType(); - PsiElementFactory factory = JavaPsiFacade.getInstance(myClass.getProject()).getElementFactory(); + PsiElementFactory factory = JavaPsiFacade.getInstance(myContext.getProject()).getElementFactory(); PsiType newType = type.createArrayType(); PsiDeclarationStatement variableDeclarationStatement; @@ -195,9 +195,9 @@ public class VariableAccessFromInnerClassFix implements IntentionAction { } private void copyToFinal() throws IncorrectOperationException { - PsiManager psiManager = myClass.getManager(); + PsiManager psiManager = myContext.getManager(); PsiElementFactory factory = JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory(); - PsiExpression initializer = factory.createExpressionFromText(myVariable.getName(), myClass); + PsiExpression initializer = factory.createExpressionFromText(myVariable.getName(), myContext); String newName = suggestNewName(psiManager.getProject(), myVariable); PsiType type = myVariable.getType(); PsiDeclarationStatement copyDecl = factory.createVariableDeclarationStatement(newName, type, initializer); @@ -206,7 +206,7 @@ public class VariableAccessFromInnerClassFix implements IntentionAction { PsiElement statement = getStatementToInsertBefore(); if (statement == null) return; PsiExpression newExpression = factory.createExpressionFromText(newName, myVariable); - replaceReferences(myClass, myVariable, newExpression); + replaceReferences(myContext, myVariable, newExpression); if (RefactoringUtil.isLoopOrIf(statement.getParent())) { RefactoringUtil.putStatementInLoopBody(copyDecl, statement.getParent(), statement); } else { @@ -219,7 +219,7 @@ public class VariableAccessFromInnerClassFix implements IntentionAction { ? ((PsiParameter)myVariable).getDeclarationScope() : PsiUtil.getVariableCodeBlock(myVariable, null); if (declarationScope == null) return null; - PsiElement statement = myClass; + PsiElement statement = myContext; nextInnerClass: do { statement = RefactoringUtil.getParentStatement(statement, false); @@ -291,11 +291,11 @@ public class VariableAccessFromInnerClassFix implements IntentionAction { int type = MAKE_FINAL; for (PsiReferenceExpression expression : outerReferences) { // if it happens that variable referenced from another inner class, make sure it can be make final from there - PsiClass innerClass = HighlightControlFlowUtil.getInnerClassVariableReferencedFrom(variable, expression); + PsiElement innerScope = HighlightControlFlowUtil.getInnerClassVariableReferencedFrom(variable, expression); - if (innerClass != null) { + if (innerScope != null) { int thisType = MAKE_FINAL; - if (writtenInside(variable, innerClass)) { + if (writtenInside(variable, innerScope)) { // cannot make parameter array if (variable instanceof PsiParameter) return -1; thisType = MAKE_ARRAY; diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/CaseColonFixer.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/CaseColonFixer.java new file mode 100644 index 000000000000..de32027c4616 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/CaseColonFixer.java @@ -0,0 +1,35 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.editorActions.smartEnter; + +import com.intellij.openapi.editor.Editor; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiSwitchLabelStatement; +import com.intellij.util.IncorrectOperationException; + +/** + * @author peter + */ +public class CaseColonFixer implements Fixer { + @Override + public void apply(Editor editor, JavaSmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException { + if (psiElement instanceof PsiSwitchLabelStatement && + ((PsiSwitchLabelStatement)psiElement).getCaseValue() != null && + !psiElement.getText().endsWith(":")) { + editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), ":"); + } + } +} diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/JavaSmartEnterProcessor.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/JavaSmartEnterProcessor.java index 4df807f561b2..cea07113fe24 100644 --- a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/JavaSmartEnterProcessor.java +++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/JavaSmartEnterProcessor.java @@ -58,6 +58,7 @@ public class JavaSmartEnterProcessor extends SmartEnterProcessor { fixers.add(new WhileConditionFixer()); fixers.add(new CatchDeclarationFixer()); fixers.add(new SwitchExpressionFixer()); + fixers.add(new CaseColonFixer()); fixers.add(new DoWhileConditionFixer()); fixers.add(new BlockBraceFixer()); fixers.add(new MissingIfBranchesFixer()); diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java index 5f95da053db3..c8a6cfa0271f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java @@ -547,8 +547,8 @@ public class QuickFixFactoryImpl extends QuickFixFactory { @NotNull @Override - public IntentionAction createVariableAccessFromInnerClassFix(@NotNull PsiVariable variable, @NotNull PsiClass aClass) { - return new VariableAccessFromInnerClassFix(variable, aClass); + public IntentionAction createVariableAccessFromInnerClassFix(@NotNull PsiVariable variable, @NotNull PsiElement scope) { + return new VariableAccessFromInnerClassFix(variable, scope); } @NotNull diff --git a/java/java-impl/src/com/intellij/codeInsight/lookup/VariableLookupItem.java b/java/java-impl/src/com/intellij/codeInsight/lookup/VariableLookupItem.java index 9f23dba0b7df..21e32a3e3aeb 100644 --- a/java/java-impl/src/com/intellij/codeInsight/lookup/VariableLookupItem.java +++ b/java/java-impl/src/com/intellij/codeInsight/lookup/VariableLookupItem.java @@ -123,7 +123,10 @@ public class VariableLookupItem extends LookupItem<PsiVariable> implements Typed } ref = PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getTailOffset() - 1, PsiReferenceExpression.class, false); - makeVariableFinalIfNeeded(context, ref); + PsiElement target = ref == null ? null : ref.resolve(); + if (target instanceof PsiLocalVariable || target instanceof PsiParameter) { + makeFinalIfNeeded(context, (PsiVariable)target); + } final char completionChar = context.getCompletionChar(); if (completionChar == '=') { @@ -151,22 +154,16 @@ public class VariableLookupItem extends LookupItem<PsiVariable> implements Typed } } - private static void makeVariableFinalIfNeeded(InsertionContext context, @Nullable PsiReferenceExpression ref) { + public static void makeFinalIfNeeded(@NotNull InsertionContext context, @NotNull PsiVariable variable) { + PsiElement place = context.getFile().findElementAt(context.getTailOffset() - 1); if (!Registry.is("java.completion.make.outer.variables.final") || - ref == null || PsiUtil.isLanguageLevel8OrHigher(ref) || JspPsiUtil.isInJspFile(ref)) { + place == null || PsiUtil.isLanguageLevel8OrHigher(place) || JspPsiUtil.isInJspFile(place)) { return; } - PsiElement target = ref.resolve(); - if (target instanceof PsiLocalVariable || target instanceof PsiParameter) { - PsiClass placeClass = PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getTailOffset() - 1, PsiClass.class, false); - if (placeClass != null && !PsiTreeUtil.isAncestor(placeClass, target, true) && - !HighlightControlFlowUtil.isReassigned((PsiVariable)target, new HashMap<PsiElement, Collection<ControlFlowUtil.VariableInfo>>())) { - PsiModifierList modifierList = ((PsiVariable)target).getModifierList(); - if (modifierList != null) { - modifierList.setModifierProperty(PsiModifier.FINAL, true); - } - } + if (HighlightControlFlowUtil.getInnerClassVariableReferencedFrom(variable, place) != null && + !HighlightControlFlowUtil.isReassigned(variable, new HashMap<PsiElement, Collection<ControlFlowUtil.VariableInfo>>())) { + PsiUtil.setModifierProperty(variable, PsiModifier.FINAL, true); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplateCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplateCompletionContributor.java index b6a7b5f687ce..eb6b585f0ec1 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplateCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplateCompletionContributor.java @@ -21,34 +21,19 @@ import com.intellij.codeInsight.template.CustomLiveTemplate; import com.intellij.codeInsight.template.impl.TemplateManagerImpl; import com.intellij.codeInsight.template.postfix.templates.PostfixLiveTemplate; import com.intellij.openapi.editor.Editor; -import com.intellij.patterns.ElementPattern; -import com.intellij.psi.JavaTokenType; -import com.intellij.psi.PsiElement; +import com.intellij.patterns.PlatformPatterns; import com.intellij.psi.PsiFile; -import com.intellij.psi.impl.source.tree.ElementType; -import com.intellij.psi.tree.TokenSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import static com.intellij.patterns.PsiJavaPatterns.psiElement; -import static com.intellij.patterns.StandardPatterns.string; - public class PostfixTemplateCompletionContributor extends CompletionContributor { - private static final TokenSet SUITABLE_ELEMENTS = TokenSet.orSet(ElementType.KEYWORD_BIT_SET, - ElementType.LITERAL_BIT_SET, - TokenSet.create(JavaTokenType.IDENTIFIER)); - public PostfixTemplateCompletionContributor() { - extend(CompletionType.BASIC, identifierAfterDot(), new PostfixTemplatesCompletionProvider()); + extend(CompletionType.BASIC, PlatformPatterns.psiElement(), new PostfixTemplatesCompletionProvider()); } @Nullable - public static PostfixLiveTemplate getPostfixLiveTemplate(@NotNull PsiFile file, @NotNull Editor editor) { + public static PostfixLiveTemplate getPostfixLiveTemplate(@NotNull PsiFile file, @NotNull Editor editor) { PostfixLiveTemplate postfixLiveTemplate = CustomLiveTemplate.EP_NAME.findExtension(PostfixLiveTemplate.class); return postfixLiveTemplate != null && TemplateManagerImpl.isApplicable(postfixLiveTemplate, editor, file) ? postfixLiveTemplate : null; } - - private static ElementPattern<? extends PsiElement> identifierAfterDot() { - return psiElement().withElementType(SUITABLE_ELEMENTS).afterLeaf(psiElement().withText(string().contains("."))); - } } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplateLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplateLookupElement.java index 0aeba2baaced..c01f6073845a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplateLookupElement.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplateLookupElement.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,8 @@ import com.intellij.codeInsight.lookup.LookupElementPresentation; import com.intellij.codeInsight.template.impl.CustomLiveTemplateLookupElement; import com.intellij.codeInsight.template.postfix.templates.PostfixLiveTemplate; import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate; -import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; public class PostfixTemplateLookupElement extends CustomLiveTemplateLookupElement { @@ -30,7 +31,7 @@ public class PostfixTemplateLookupElement extends CustomLiveTemplateLookupElemen @NotNull PostfixTemplate postfixTemplate, @NotNull String templateKey, boolean sudden) { - super(liveTemplate, templateKey, postfixTemplate.getPresentableName(), postfixTemplate.getDescription(), sudden, true); + super(liveTemplate, templateKey, StringUtil.trimStart(templateKey, "."), postfixTemplate.getDescription(), sudden, true); myTemplate = postfixTemplate; } @@ -43,15 +44,11 @@ public class PostfixTemplateLookupElement extends CustomLiveTemplateLookupElemen public void renderElement(LookupElementPresentation presentation) { super.renderElement(presentation); if (sudden) { - presentation.setTailText(" " + arrow() + " " + myTemplate.getExample()); + presentation.setTailText(" " + UIUtil.rightArrow() + " " + myTemplate.getExample()); } else { presentation.setTypeText(myTemplate.getExample()); presentation.setTypeGrayed(true); } } - - private static String arrow() { - return SystemInfo.isMac ? "→" : "->"; - } } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplatesCompletionProvider.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplatesCompletionProvider.java index db253a6808b1..ec0aead68085 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplatesCompletionProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplatesCompletionProvider.java @@ -19,6 +19,7 @@ import com.intellij.codeInsight.completion.CompletionParameters; import com.intellij.codeInsight.completion.CompletionProvider; import com.intellij.codeInsight.completion.CompletionResultSet; import com.intellij.codeInsight.completion.PrefixMatcher; +import com.intellij.codeInsight.template.CustomTemplateCallback; import com.intellij.codeInsight.template.impl.LiveTemplateCompletionContributor; import com.intellij.codeInsight.template.postfix.settings.PostfixTemplatesSettings; import com.intellij.codeInsight.template.postfix.templates.PostfixLiveTemplate; @@ -42,11 +43,12 @@ class PostfixTemplatesCompletionProvider extends CompletionProvider<CompletionPa PostfixLiveTemplate postfixLiveTemplate = getPostfixLiveTemplate(parameters.getOriginalFile(), parameters.getEditor()); if (postfixLiveTemplate != null) { postfixLiveTemplate.addCompletions(parameters, result.withPrefixMatcher(new MyPrefixMatcher(result.getPrefixMatcher().getPrefix()))); - CharSequence documentContent = parameters.getEditor().getDocument().getCharsSequence(); - String possibleKey = postfixLiveTemplate.computeTemplateKeyWithoutContextChecking(documentContent, parameters.getOffset()); + String possibleKey = postfixLiveTemplate.computeTemplateKeyWithoutContextChecking( + new CustomTemplateCallback(parameters.getEditor(), parameters.getOriginalFile(), false)); if (possibleKey != null) { result = result.withPrefixMatcher(possibleKey); - result.restartCompletionOnPrefixChange(StandardPatterns.string().oneOf(postfixLiveTemplate.getAllTemplateKeys())); + result.restartCompletionOnPrefixChange( + StandardPatterns.string().oneOf(postfixLiveTemplate.getAllTemplateKeys(parameters.getOriginalFile(), parameters.getOffset()))); } } } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixTemplatesConfigurable.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixTemplatesConfigurable.java index 75c7d93b515a..90d4eed6e2b9 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixTemplatesConfigurable.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixTemplatesConfigurable.java @@ -19,7 +19,11 @@ import com.intellij.application.options.editor.EditorOptionsProvider; import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.codeInsight.template.impl.LiveTemplateCompletionContributor; import com.intellij.codeInsight.template.impl.TemplateSettings; +import com.intellij.codeInsight.template.postfix.templates.LanguagePostfixTemplate; import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate; +import com.intellij.codeInsight.template.postfix.templates.PostfixTemplateProvider; +import com.intellij.lang.LanguageExtensionPoint; +import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.SearchableConfigurable; @@ -34,8 +38,9 @@ import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.*; -import java.util.*; +import java.util.Comparator; import java.util.List; +import java.util.Map; public class PostfixTemplatesConfigurable implements SearchableConfigurable, EditorOptionsProvider, Configurable.NoScroll { @Nullable @@ -61,7 +66,14 @@ public class PostfixTemplatesConfigurable implements SearchableConfigurable, Edi } myTemplatesSettings = settings; - List<PostfixTemplate> templates = Arrays.asList(PostfixTemplate.EP_NAME.getExtensions()); + + LanguageExtensionPoint[] extensions = new ExtensionPointName<LanguageExtensionPoint>(LanguagePostfixTemplate.EP_NAME).getExtensions(); + + List<PostfixTemplate> templates = ContainerUtil.newArrayList(); + for (LanguageExtensionPoint extension : extensions) { + templates.addAll(((PostfixTemplateProvider)extension.getInstance()).getTemplates()); + } + ContainerUtil.sort(templates, new Comparator<PostfixTemplate>() { @Override public int compare(PostfixTemplate o1, PostfixTemplate o2) { @@ -184,7 +196,7 @@ public class PostfixTemplatesConfigurable implements SearchableConfigurable, Edi private static String shortcutToString(char shortcut) { if (shortcut == TemplateSettings.SPACE_CHAR) { return SPACE; - } + } if (shortcut == TemplateSettings.ENTER_CHAR) { return ENTER; } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixTemplatesListPanel.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixTemplatesListPanel.java index 0c21e04b4c97..4ecc8c0ee4ac 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixTemplatesListPanel.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixTemplatesListPanel.java @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.codeInsight.template.postfix.settings; import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate; @@ -29,7 +44,7 @@ public class PostfixTemplatesListPanel { @NotNull @Override public String fun(@NotNull PostfixTemplate template) { - return template.getKey().replaceFirst(".", ""); + return template.getKey().replaceFirst("\\.", ""); } }; @@ -114,7 +129,9 @@ public class PostfixTemplatesListPanel { public void setState(@NotNull Map<String, Boolean> templatesState) { myTemplatesState.clear(); for (Map.Entry<String, Boolean> entry : templatesState.entrySet()) { - myTemplatesState.put(entry.getKey(), entry.getValue()); + if (!entry.getValue()) { + myTemplatesState.put(entry.getKey(), entry.getValue()); + } } } @@ -172,7 +189,13 @@ public class PostfixTemplatesListPanel { @Override public void setValue(@NotNull PostfixTemplate template, Boolean value) { - myTemplatesState.put(template.getKey(), value); + String key = template.getKey(); + if (value) { + myTemplatesState.remove(key); + } + else { + myTemplatesState.put(key, value); + } } } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/BooleanPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/BooleanPostfixTemplate.java index ab6f90eaa752..f8700bed4644 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/BooleanPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/BooleanPostfixTemplate.java @@ -28,7 +28,7 @@ abstract public class BooleanPostfixTemplate extends PostfixTemplate { @Override public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - PsiExpression topmostExpression = getTopmostExpression(context); + PsiExpression topmostExpression = PostfixTemplatesUtils.getTopmostExpression(context); return topmostExpression != null && PostfixTemplatesUtils.isBoolean(topmostExpression.getType()); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ElseStatementPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ElseStatementPostfixTemplate.java index 37187455f40c..a148a1bf8896 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ElseStatementPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ElseStatementPostfixTemplate.java @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.codeInsight.template.postfix.templates; import com.intellij.codeInsight.CodeInsightServicesUtil; @@ -15,7 +30,7 @@ public class ElseStatementPostfixTemplate extends BooleanPostfixTemplate { @Override public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PsiExpression expression = getTopmostExpression(context); + PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context); assert expression != null; PsiExpression invertedExpression = (PsiExpression)expression.replace(CodeInsightServicesUtil.invertCondition(expression)); TextRange range = PostfixTemplatesUtils.ifStatement(invertedExpression.getProject(), editor, invertedExpression); diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ExpressionPostfixTemplateWithChooser.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ExpressionPostfixTemplateWithChooser.java index 8de536551ab5..3bd7928c3e1c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ExpressionPostfixTemplateWithChooser.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ExpressionPostfixTemplateWithChooser.java @@ -42,6 +42,13 @@ public abstract class ExpressionPostfixTemplateWithChooser extends PostfixTempla super(name, description, example); } + protected ExpressionPostfixTemplateWithChooser(@NotNull String name, + @NotNull String key, + @NotNull String description, + @NotNull String example) { + super(name, key, description, example); + } + @Override public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { return !getExpressions(context, copyDocument, newOffset).isEmpty(); @@ -75,20 +82,22 @@ public abstract class ExpressionPostfixTemplateWithChooser extends PostfixTempla } }, new PsiExpressionTrimRenderer.RenderFunction(), - "Expressions", 0, ScopeHighlighter.NATURAL_RANGER); + "Expressions", 0, ScopeHighlighter.NATURAL_RANGER + ); } } @NotNull protected List<PsiExpression> getExpressions(@NotNull PsiElement context, @NotNull Document document, final int offset) { - List<PsiExpression> expressions = ContainerUtil.filter(IntroduceVariableBase.collectExpressions(context.getContainingFile(), document, - Math.max(offset - 1, 0), false), + List<PsiExpression> expressions = ContainerUtil.filter(IntroduceVariableBase.collectExpressions(context.getContainingFile(), document, + Math.max(offset - 1, 0), false), new Condition<PsiExpression>() { @Override public boolean value(PsiExpression expression) { return expression.getTextRange().getEndOffset() == offset; } - }); + } + ); return ContainerUtil.filter(expressions.isEmpty() ? maybeTopmostExpression(context) : expressions, getTypeCondition()); } @@ -100,7 +109,7 @@ public abstract class ExpressionPostfixTemplateWithChooser extends PostfixTempla @NotNull private static List<PsiExpression> maybeTopmostExpression(@NotNull PsiElement context) { - PsiExpression expression = getTopmostExpression(context); + PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context); PsiType type = expression != null ? expression.getType() : null; if (type == null || PsiType.VOID.equals(type)) return ContainerUtil.emptyList(); return ContainerUtil.createMaybeSingletonList(expression); diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForIndexedPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForIndexedPostfixTemplate.java index c353c8d39145..bf025d17741f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForIndexedPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForIndexedPostfixTemplate.java @@ -37,7 +37,7 @@ public abstract class ForIndexedPostfixTemplate extends PostfixTemplate { @Override public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - PsiExpression expr = getTopmostExpression(context); + PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); return expr != null && (PostfixTemplatesUtils.isNumber(expr.getType()) || PostfixTemplatesUtils.isArray(expr.getType()) || PostfixTemplatesUtils.isIterable(expr.getType())); @@ -45,7 +45,7 @@ public abstract class ForIndexedPostfixTemplate extends PostfixTemplate { @Override public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PsiExpression expr = getTopmostExpression(context); + PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); if (expr == null) { PostfixTemplatesUtils.showErrorHint(context.getProject(), editor); return; diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForeachPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForeachPostfixTemplate.java index aabf47c8eaa1..72bbb4f703bf 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForeachPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForeachPostfixTemplate.java @@ -37,13 +37,13 @@ public class ForeachPostfixTemplate extends PostfixTemplate { @Override public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - PsiExpression expr = getTopmostExpression(context); + PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); return expr != null && (PostfixTemplatesUtils.isArray(expr.getType()) || PostfixTemplatesUtils.isIterable(expr.getType())); } @Override public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PsiExpression expr = getTopmostExpression(context); + PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); if (expr == null) return; Project project = context.getProject(); diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/FormatPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/FormatPostfixTemplate.java index 5d99745168a4..a799f39ca466 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/FormatPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/FormatPostfixTemplate.java @@ -36,7 +36,7 @@ public class FormatPostfixTemplate extends PostfixTemplate { @Override public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - PsiExpression expr = getTopmostExpression(context); + PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); PsiType type = expr != null ? expr.getType() : null; return expr != null && type != null && CommonClassNames.JAVA_LANG_STRING.equals(type.getCanonicalText()); } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IfStatementPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IfStatementPostfixTemplate.java index 9610ec57c23d..812247428e51 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IfStatementPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IfStatementPostfixTemplate.java @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.codeInsight.template.postfix.templates; import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; @@ -14,7 +29,7 @@ public class IfStatementPostfixTemplate extends BooleanPostfixTemplate { @Override public void expand(@NotNull PsiElement context, @NotNull final Editor editor) { - PsiExpression expression = getTopmostExpression(context); + PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context); assert expression != null; TextRange range = PostfixTemplatesUtils.ifStatement(expression.getProject(), editor, expression); if (range != null) { diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/InstanceofExpressionPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/InstanceofExpressionPostfixTemplate.java index 8c5b58e79123..1884d099edcd 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/InstanceofExpressionPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/InstanceofExpressionPostfixTemplate.java @@ -19,7 +19,6 @@ import com.intellij.codeInsight.guess.GuessManager; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.PsiTypeLookupItem; import com.intellij.codeInsight.template.*; -import com.intellij.codeInsight.template.postfix.util.Aliases; import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; @@ -35,25 +34,30 @@ import org.jetbrains.annotations.NotNull; import java.util.LinkedHashSet; import java.util.Set; -@Aliases(".inst") public class InstanceofExpressionPostfixTemplate extends PostfixTemplate { + public InstanceofExpressionPostfixTemplate() { - super("instanceof", "Surrounds expression with instanceof", "expr instanceof SomeType ? ((SomeType) expr). : null"); + this("instanceof"); + } + + public InstanceofExpressionPostfixTemplate(String alias) { + super(alias, "Surrounds expression with instanceof", "expr instanceof SomeType ? ((SomeType) expr). : null"); } @Override public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - return PostfixTemplatesUtils.isNotPrimitiveTypeExpression(getTopmostExpression(context)); + return PostfixTemplatesUtils.isNotPrimitiveTypeExpression(PostfixTemplatesUtils.getTopmostExpression(context)); } @Override public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PsiExpression expression = getTopmostExpression(context); + PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context); if (!PostfixTemplatesUtils.isNotPrimitiveTypeExpression(expression)) return; surroundExpression(context.getProject(), editor, expression); } - private static void surroundExpression(@NotNull Project project, @NotNull Editor editor, @NotNull PsiExpression expr) throws IncorrectOperationException { + private static void surroundExpression(@NotNull Project project, @NotNull Editor editor, @NotNull PsiExpression expr) + throws IncorrectOperationException { assert expr.isValid(); PsiType[] types = GuessManager.getInstance(project).guessTypeToCast(expr); final boolean parenthesesNeeded = expr instanceof PsiPolyadicExpression || diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateProvider.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateProvider.java new file mode 100644 index 000000000000..2ee071b98559 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateProvider.java @@ -0,0 +1,130 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.template.postfix.templates; + +import com.intellij.codeInsight.completion.CompletionInitializationContext; +import com.intellij.codeInsight.completion.JavaCompletionContributor; +import com.intellij.codeInsight.template.CustomTemplateCallback; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.util.Ref; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.Set; + + +public class JavaPostfixTemplateProvider implements PostfixTemplateProvider { + private final Set<PostfixTemplate> templates; + + + public JavaPostfixTemplateProvider() { + templates = ContainerUtil.newHashSet(new AssertStatementPostfixTemplate(), + new CastExpressionPostfixTemplate(), + new ElseStatementPostfixTemplate(), + new ForAscendingPostfixTemplate(), + new ForDescendingPostfixTemplate(), + new ForeachPostfixTemplate(), + new FormatPostfixTemplate(), + new IfStatementPostfixTemplate(), + new InstanceofExpressionPostfixTemplate(), + new InstanceofExpressionPostfixTemplate("inst"), + new IntroduceFieldPostfixTemplate(), + new IntroduceVariablePostfixTemplate(), + new IsNullCheckPostfixTemplate(), + new NotExpressionPostfixTemplate(), + new NotExpressionPostfixTemplate("!"), + new NotNullCheckPostfixTemplate(), + new NotNullCheckPostfixTemplate("nn"), + new ParenthesizedExpressionPostfixTemplate(), + new ReturnStatementPostfixTemplate(), + new SoutPostfixTemplate(), + new SwitchStatementPostfixTemplate(), + new SynchronizedStatementPostfixTemplate(), + new ThrowExceptionPostfixTemplate(), + new TryStatementPostfixTemplate(), + new TryWithResourcesPostfixTemplate(), + new WhileStatementPostfixTemplate()); + } + + @NotNull + @Override + public Set<PostfixTemplate> getTemplates() { + return templates; + } + + @Override + public boolean isTerminalSymbol(char currentChar) { + return currentChar == '.' || currentChar == '!'; + } + + @NotNull + @Override + public PsiElement preExpand(@NotNull Editor editor, @NotNull PsiElement context, int offset, @NotNull final String key) { + + return addSemicolonIfNeeded(editor, editor.getDocument(), context, offset - key.length()); + } + + @NotNull + @Override + public PsiFile preCheck(@NotNull Editor editor, @NotNull PsiFile copyFile, int currentOffset) { + Document document = copyFile.getViewProvider().getDocument(); + assert document != null; + CharSequence sequence = document.getCharsSequence(); + StringBuilder fileContentWithoutKey = new StringBuilder(sequence); + if (isSemicolonNeeded(copyFile, editor)) { + fileContentWithoutKey.insert(currentOffset, ';'); + copyFile = PostfixLiveTemplate.copyFile(copyFile, fileContentWithoutKey); + } + + return copyFile; + } + + @NotNull + private static PsiElement addSemicolonIfNeeded(@NotNull final Editor editor, + @NotNull final Document document, + @NotNull final PsiElement context, + final int offset) { + ApplicationManager.getApplication().assertIsDispatchThread(); + + final Ref<PsiElement> newContext = Ref.create(context); + final PsiFile file = context.getContainingFile(); + if (isSemicolonNeeded(file, editor)) { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() { + public void run() { + document.insertString(offset, ";"); + PsiDocumentManager.getInstance(context.getProject()).commitDocument(document); + newContext.set(CustomTemplateCallback.getContext(file, offset - 1)); + } + }); + } + }); + } + return newContext.get(); + } + + private static boolean isSemicolonNeeded(@NotNull PsiFile file, @NotNull Editor editor) { + return JavaCompletionContributor.semicolonNeeded(editor, file, CompletionInitializationContext.calcStartOffset(editor)); + } +} diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/LanguagePostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/LanguagePostfixTemplate.java new file mode 100644 index 000000000000..2360d9721ab8 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/LanguagePostfixTemplate.java @@ -0,0 +1,27 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.template.postfix.templates; + +import com.intellij.lang.LanguageExtension; + +public class LanguagePostfixTemplate extends LanguageExtension<PostfixTemplateProvider> { + public static final LanguagePostfixTemplate LANG_EP = new LanguagePostfixTemplate(); + public static final String EP_NAME = "com.intellij.codeInsight.template.postfixTemplateProvider"; + + private LanguagePostfixTemplate() { + super(EP_NAME); + } +} diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NonVoidPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NonVoidPostfixTemplate.java index 906a943e15e6..09757e53e826 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NonVoidPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NonVoidPostfixTemplate.java @@ -28,7 +28,7 @@ abstract public class NonVoidPostfixTemplate extends PostfixTemplate { @Override public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - PsiExpression expr = getTopmostExpression(context); + PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); return expr != null && PostfixTemplatesUtils.isNonVoid(expr.getType()); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java index 9900c0a4c57d..e2e3db8b8be6 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java @@ -16,14 +16,12 @@ package com.intellij.codeInsight.template.postfix.templates; import com.intellij.codeInsight.CodeInsightServicesUtil; -import com.intellij.codeInsight.template.postfix.util.Aliases; import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.util.Condition; import com.intellij.psi.PsiExpression; import org.jetbrains.annotations.NotNull; -@Aliases("!") public class NotExpressionPostfixTemplate extends ExpressionPostfixTemplateWithChooser { private static final Condition<PsiExpression> BOOLEAN_TYPE_CONDITION = new Condition<PsiExpression>() { @Override @@ -36,6 +34,10 @@ public class NotExpressionPostfixTemplate extends ExpressionPostfixTemplateWithC super("not", "Negates boolean expression", "!expr"); } + public NotExpressionPostfixTemplate(String alias) { + super(alias, alias, "Negates boolean expression", "!expr"); + } + @Override protected void doIt(@NotNull Editor editor, @NotNull PsiExpression expression) { expression.replace(CodeInsightServicesUtil.invertCondition(expression)); diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotNullCheckPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotNullCheckPostfixTemplate.java index e4bde3241fee..ea2480f86a0e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotNullCheckPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotNullCheckPostfixTemplate.java @@ -1,12 +1,30 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.codeInsight.template.postfix.templates; -import com.intellij.codeInsight.template.postfix.util.Aliases; import org.jetbrains.annotations.NotNull; -@Aliases(".nn") public class NotNullCheckPostfixTemplate extends NullCheckPostfixTemplate { + public NotNullCheckPostfixTemplate() { - super("notnull", "Checks expression to be not-null", "if (expr != null)"); + this("notnull"); + } + + public NotNullCheckPostfixTemplate(String alias) { + super(alias, "Checks expression to be not-null", "if (expr != null)"); } @NotNull diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NullCheckPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NullCheckPostfixTemplate.java index 6a9b6769e548..c7ad21b2fb11 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NullCheckPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NullCheckPostfixTemplate.java @@ -39,12 +39,12 @@ public abstract class NullCheckPostfixTemplate extends PostfixTemplate { @Override public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - return PostfixTemplatesUtils.isNotPrimitiveTypeExpression(getTopmostExpression(context)); + return PostfixTemplatesUtils.isNotPrimitiveTypeExpression(PostfixTemplatesUtils.getTopmostExpression(context)); } @Override public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PsiExpression expr = getTopmostExpression(context); + PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); if (!PostfixTemplatesUtils.isNotPrimitiveTypeExpression(expr)) return; Project project = expr.getProject(); diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixLiveTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixLiveTemplate.java index a165dcb0ed17..8fd2e725d560 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixLiveTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixLiveTemplate.java @@ -15,17 +15,15 @@ */ package com.intellij.codeInsight.template.postfix.templates; -import com.intellij.codeInsight.completion.CompletionInitializationContext; -import com.intellij.codeInsight.completion.JavaCompletionContributor; +import com.google.common.collect.Sets; import com.intellij.codeInsight.template.CustomLiveTemplateBase; import com.intellij.codeInsight.template.CustomTemplateCallback; import com.intellij.codeInsight.template.impl.CustomLiveTemplateLookupElement; import com.intellij.codeInsight.template.impl.TemplateSettings; import com.intellij.codeInsight.template.postfix.completion.PostfixTemplateLookupElement; import com.intellij.codeInsight.template.postfix.settings.PostfixTemplatesSettings; -import com.intellij.codeInsight.template.postfix.util.Aliases; import com.intellij.featureStatistics.FeatureUsageTracker; -import com.intellij.lang.java.JavaLanguage; +import com.intellij.lang.Language; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.command.undo.UndoConstants; @@ -33,7 +31,6 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDocumentManager; @@ -42,71 +39,41 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFileFactory; import com.intellij.psi.util.PsiUtilCore; import com.intellij.util.containers.ContainerUtil; -import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; -import java.util.HashMap; -import java.util.Map; import java.util.Set; +import static com.intellij.codeInsight.template.postfix.templates.LanguagePostfixTemplate.LANG_EP; + public class PostfixLiveTemplate extends CustomLiveTemplateBase { public static final String POSTFIX_TEMPLATE_ID = "POSTFIX_TEMPLATE_ID"; - private static final Logger LOG = Logger.getInstance(PostfixLiveTemplate.class); - private final HashMap<String, PostfixTemplate> myTemplates = ContainerUtil.newHashMap(); - - public PostfixLiveTemplate() { - for (PostfixTemplate template : PostfixTemplate.EP_NAME.getExtensions()) { - register(template.getKey(), template); - Aliases aliases = template.getClass().getAnnotation(Aliases.class); - if (aliases != null) { - for (String key : aliases.value()) { - register(key, template); - } - } - } - } - private void register(@NotNull String key, @NotNull PostfixTemplate template) { - PostfixTemplate registered = myTemplates.put(key, template); - if (registered != null) { - LOG.error("Can't register postfix template. Duplicated key: " + template.getKey()); + @NotNull + public Set<String> getAllTemplateKeys(PsiFile file, int offset) { + Set<String> keys = Sets.newHashSet(); + Language language = PsiUtilCore.getLanguageAtOffset(file, offset); + for (PostfixTemplateProvider provider : LANG_EP.allForLanguage(language)) { + keys.addAll(getKeys(provider)); } + return keys; } @Nullable - @Override - public String computeTemplateKey(@NotNull CustomTemplateCallback callback) { - Editor editor = callback.getEditor(); - String key = computeTemplateKeyWithoutContextChecking(editor.getDocument().getCharsSequence(), editor.getCaretModel().getOffset()); - if (key == null) return null; - return isApplicableTemplate(getTemplateByKey(key), key, callback.getContext().getContainingFile(), editor) ? key : null; - } - - @Nullable - @Override - public String computeTemplateKeyWithoutContextChecking(@NotNull CustomTemplateCallback callback) { - Editor editor = callback.getEditor(); - return computeTemplateKeyWithoutContextChecking(editor.getDocument().getCharsSequence(), editor.getCaretModel().getOffset()); - } - - @Override - public boolean supportsMultiCaret() { - return false; - } - - @Nullable - public String computeTemplateKeyWithoutContextChecking(@NotNull CharSequence documentContent, int currentOffset) { + private static String computeTemplateKeyWithoutContextChecking(@NotNull PostfixTemplateProvider provider, + @NotNull CharSequence documentContent, + int currentOffset) { int startOffset = currentOffset; if (documentContent.length() < startOffset) { return null; } + while (startOffset > 0) { char currentChar = documentContent.charAt(startOffset - 1); if (!Character.isJavaIdentifierPart(currentChar)) { - if (currentChar != '.' && currentChar != '!') { + if (!provider.isTerminalSymbol(currentChar)) { return null; } startOffset--; @@ -117,23 +84,64 @@ public class PostfixLiveTemplate extends CustomLiveTemplateBase { return String.valueOf(documentContent.subSequence(startOffset, currentOffset)); } + @Nullable + @Override + public String computeTemplateKey(@NotNull CustomTemplateCallback callback) { + Editor editor = callback.getEditor(); + CharSequence charsSequence = editor.getDocument().getCharsSequence(); + int offset = editor.getCaretModel().getOffset(); + for (PostfixTemplateProvider provider : LANG_EP.allForLanguage(getLanguage(callback))) { + String key = computeTemplateKeyWithoutContextChecking(provider, charsSequence, offset); + if (key != null && isApplicableTemplate(provider, key, callback.getFile(), editor)) { + return key; + } + } + return null; + } + + @Nullable + @Override + public String computeTemplateKeyWithoutContextChecking(@NotNull CustomTemplateCallback callback) { + Editor editor = callback.getEditor(); + int currentOffset = editor.getCaretModel().getOffset(); + for (PostfixTemplateProvider provider : LANG_EP.allForLanguage(getLanguage(callback))) { + String key = computeTemplateKeyWithoutContextChecking(provider, editor.getDocument().getCharsSequence(), currentOffset); + if (key != null) return key; + } + return null; + } + + @Override + public boolean supportsMultiCaret() { + return false; + } + @Override public void expand(@NotNull final String key, @NotNull final CustomTemplateCallback callback) { ApplicationManager.getApplication().assertIsDispatchThread(); - FeatureUsageTracker.getInstance().triggerFeatureUsed("editing.completion.postfix"); - final PostfixTemplate template = getTemplateByKey(key); - final Editor editor = callback.getEditor(); - final PsiFile file = callback.getContext().getContainingFile(); - if (isApplicableTemplate(template, key, file, editor)) { - int currentOffset = editor.getCaretModel().getOffset(); - PsiElement newContext = deleteTemplateKey(file, editor.getDocument(), currentOffset, key); - newContext = addSemicolonIfNeeded(editor, editor.getDocument(), newContext, currentOffset - key.length()); - expandTemplate(template, editor, newContext); + Editor editor = callback.getEditor(); + for (PostfixTemplateProvider provider : LANG_EP.allForLanguage(getLanguage(callback))) { + PostfixTemplate postfixTemplate = getTemplate(provider, key); + if (postfixTemplate != null) { + final PsiFile file = callback.getContext().getContainingFile(); + if (isApplicableTemplate(provider, key, file, editor)) { + int currentOffset = editor.getCaretModel().getOffset(); + PsiElement newContext = deleteTemplateKey(file, editor.getDocument(), currentOffset, key); + newContext = provider.preExpand(editor, newContext, currentOffset, key); + expandTemplate(postfixTemplate, editor, newContext); + } + // don't care about errors in multiCaret mode + else if (editor.getCaretModel().getAllCarets().size() == 1) { + LOG.error("Template not found by key: " + key); + } + return; + } } + // don't care about errors in multiCaret mode - else if (editor.getCaretModel().getAllCarets().size() == 1) { + if (editor.getCaretModel().getAllCarets().size() == 1) { LOG.error("Template not found by key: " + key); } } @@ -141,11 +149,16 @@ public class PostfixLiveTemplate extends CustomLiveTemplateBase { @Override public boolean isApplicable(PsiFile file, int offset, boolean wrapping) { PostfixTemplatesSettings settings = PostfixTemplatesSettings.getInstance(); - if (wrapping || file == null || settings == null || !settings.isPostfixTemplatesEnabled() || - PsiUtilCore.getLanguageAtOffset(file, offset) != JavaLanguage.INSTANCE) { + if (wrapping || file == null || settings == null || !settings.isPostfixTemplatesEnabled()) { return false; } - return StringUtil.isNotEmpty(computeTemplateKeyWithoutContextChecking(file.getText(), offset + 1)); + Language language = PsiUtilCore.getLanguageAtOffset(file, offset); + for (PostfixTemplateProvider provider : LANG_EP.allForLanguage(language)) { + if (StringUtil.isNotEmpty(computeTemplateKeyWithoutContextChecking(provider, file.getText(), offset + 1))) { + return true; + } + } + return false; } @Override @@ -177,30 +190,24 @@ public class PostfixLiveTemplate extends CustomLiveTemplateBase { @NotNull @Override - public Collection<? extends CustomLiveTemplateLookupElement> getLookupElements(@NotNull PsiFile file, @NotNull Editor editor, int offset) { - String key = computeTemplateKeyWithoutContextChecking(editor.getDocument().getCharsSequence(), offset); - if (key != null && editor.getCaretModel().getCaretCount() == 1) { - Map<String, CustomLiveTemplateLookupElement> result = ContainerUtil.newHashMap(); - Condition<PostfixTemplate> isApplicationTemplateFunction = createIsApplicationTemplateFunction(key, file, editor); - for (Map.Entry<String, PostfixTemplate> entry : myTemplates.entrySet()) { - PostfixTemplate postfixTemplate = entry.getValue(); - if (entry.getKey().startsWith(key) && isApplicationTemplateFunction.value(postfixTemplate)) { - result.put(postfixTemplate.getKey(), new PostfixTemplateLookupElement(this, postfixTemplate, entry.getKey(), false)); + public Collection<? extends CustomLiveTemplateLookupElement> getLookupElements(@NotNull PsiFile file, + @NotNull Editor editor, + int offset) { + Collection<CustomLiveTemplateLookupElement> result = ContainerUtil.newHashSet(); + CustomTemplateCallback callback = new CustomTemplateCallback(editor, file, false); + for (PostfixTemplateProvider provider : LANG_EP.allForLanguage(getLanguage(callback))) { + String key = computeTemplateKeyWithoutContextChecking(callback); + if (key != null && editor.getCaretModel().getCaretCount() == 1) { + Condition<PostfixTemplate> isApplicationTemplateFunction = createIsApplicationTemplateFunction(provider, key, file, editor); + for (PostfixTemplate postfixTemplate : provider.getTemplates()) { + if (isApplicationTemplateFunction.value(postfixTemplate)) { + result.add(new PostfixTemplateLookupElement(this, postfixTemplate, postfixTemplate.getKey(), false)); + } } } - return result.values(); } - return super.getLookupElements(file, editor, offset); - } - - @NotNull - public Set<String> getAllTemplateKeys() { - return myTemplates.keySet(); - } - @Nullable - public PostfixTemplate getTemplateByKey(@NotNull String key) { - return myTemplates.get(key); + return result; } private static void expandTemplate(@NotNull final PostfixTemplate template, @@ -218,16 +225,36 @@ public class PostfixLiveTemplate extends CustomLiveTemplateBase { }); } - @Contract("null, _, _, _ -> false") - private static boolean isApplicableTemplate(@Nullable PostfixTemplate template, @NotNull String key, @NotNull PsiFile file, @NotNull Editor editor) { - return createIsApplicationTemplateFunction(key, file, editor).value(template); + + @NotNull + private static PsiElement deleteTemplateKey(@NotNull final PsiFile file, + @NotNull final Document document, + final int currentOffset, + @NotNull final String key) { + ApplicationManager.getApplication().assertIsDispatchThread(); + + final int startOffset = currentOffset - key.length(); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() { + public void run() { + document.deleteString(startOffset, currentOffset); + PsiDocumentManager.getInstance(file.getProject()).commitDocument(document); + } + }); + } + }); + return CustomTemplateCallback.getContext(file, startOffset > 0 ? startOffset - 1 : startOffset); } - - private static Condition<PostfixTemplate> createIsApplicationTemplateFunction(@NotNull String key, @NotNull PsiFile file, @NotNull Editor editor) { + + private static Condition<PostfixTemplate> createIsApplicationTemplateFunction(@NotNull PostfixTemplateProvider provider, + @NotNull String key, + @NotNull PsiFile file, + @NotNull Editor editor) { int currentOffset = editor.getCaretModel().getOffset(); final int newOffset = currentOffset - key.length(); CharSequence fileContent = editor.getDocument().getCharsSequence(); - StringBuilder fileContentWithoutKey = new StringBuilder(); fileContentWithoutKey.append(fileContent.subSequence(0, newOffset)); fileContentWithoutKey.append(fileContent.subSequence(currentOffset, fileContent.length())); @@ -238,14 +265,11 @@ public class PostfixLiveTemplate extends CustomLiveTemplateBase { return Condition.FALSE; } - if (isSemicolonNeeded(copyFile, editor)) { - fileContentWithoutKey.insert(newOffset, ';'); - copyFile = copyFile(file, fileContentWithoutKey); - copyDocument = copyFile.getViewProvider().getDocument(); - if (copyDocument == null) { - //noinspection unchecked - return Condition.FALSE; - } + copyFile = provider.preCheck(editor, copyFile, newOffset); + copyDocument = copyFile.getViewProvider().getDocument(); + if (copyDocument == null) { + //noinspection unchecked + return Condition.FALSE; } final PsiElement context = CustomTemplateCallback.getContext(copyFile, newOffset > 0 ? newOffset - 1 : newOffset); @@ -258,8 +282,9 @@ public class PostfixLiveTemplate extends CustomLiveTemplateBase { }; } + @NotNull - private static PsiFile copyFile(@NotNull PsiFile file, @NotNull StringBuilder fileContentWithoutKey) { + public static PsiFile copyFile(@NotNull PsiFile file, @NotNull StringBuilder fileContentWithoutKey) { final PsiFileFactory psiFileFactory = PsiFileFactory.getInstance(file.getProject()); PsiFile copy = psiFileFactory.createFileFromText(file.getName(), file.getFileType(), fileContentWithoutKey); VirtualFile vFile = copy.getVirtualFile(); @@ -269,55 +294,35 @@ public class PostfixLiveTemplate extends CustomLiveTemplateBase { return copy; } - @NotNull - private static PsiElement deleteTemplateKey(@NotNull final PsiFile file, - @NotNull final Document document, - final int currentOffset, - @NotNull final String key) { - ApplicationManager.getApplication().assertIsDispatchThread(); - - final int startOffset = currentOffset - key.length(); - ApplicationManager.getApplication().runWriteAction(new Runnable() { - @Override - public void run() { - CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() { - public void run() { - document.deleteString(startOffset, currentOffset); - PsiDocumentManager.getInstance(file.getProject()).commitDocument(document); - } - }); - } - }); - return CustomTemplateCallback.getContext(file, startOffset > 0 ? startOffset - 1 : startOffset); + public static boolean isApplicableTemplate(@NotNull PostfixTemplateProvider provider, + @NotNull String key, + @NotNull PsiFile file, + @NotNull Editor editor) { + return createIsApplicationTemplateFunction(provider, key, file, editor).value(getTemplate(provider, key)); } + @NotNull - private static PsiElement addSemicolonIfNeeded(@NotNull final Editor editor, - @NotNull final Document document, - @NotNull final PsiElement context, - final int offset) { - ApplicationManager.getApplication().assertIsDispatchThread(); + private static Set<String> getKeys(@NotNull PostfixTemplateProvider provider) { + Set<String> result = ContainerUtil.newHashSet(); + for (PostfixTemplate template : provider.getTemplates()) { + result.add(template.getKey()); + } - final Ref<PsiElement> newContext = Ref.create(context); - final PsiFile file = context.getContainingFile(); - if (isSemicolonNeeded(file, editor)) { - ApplicationManager.getApplication().runWriteAction(new Runnable() { - @Override - public void run() { - CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() { - public void run() { - document.insertString(offset, ";"); - PsiDocumentManager.getInstance(context.getProject()).commitDocument(document); - newContext.set(CustomTemplateCallback.getContext(file, offset - 1)); - } - }); - } - }); + return result; + } + + @Nullable + private static PostfixTemplate getTemplate(@NotNull PostfixTemplateProvider provider, @Nullable String key) { + for (PostfixTemplate template : provider.getTemplates()) { + if (template.getKey().equals(key)) { + return template; + } } - return newContext.get(); + return null; } - private static boolean isSemicolonNeeded(@NotNull PsiFile file, @NotNull Editor editor) { - return JavaCompletionContributor.semicolonNeeded(editor, file, CompletionInitializationContext.calcStartOffset(editor)); + private static Language getLanguage(@NotNull CustomTemplateCallback callback) { + return callback.getContext().getLanguage(); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplate.java index 80a68ab26650..747366d1832f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplate.java @@ -18,13 +18,8 @@ package com.intellij.codeInsight.template.postfix.templates; import com.intellij.codeInsight.template.postfix.settings.PostfixTemplatesSettings; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiExpression; -import com.intellij.psi.PsiExpressionStatement; -import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; public abstract class PostfixTemplate { @NotNull private final String myPresentableName; @@ -32,9 +27,6 @@ public abstract class PostfixTemplate { @NotNull private final String myDescription; @NotNull private final String myExample; - @NotNull - public static final ExtensionPointName<PostfixTemplate> EP_NAME = ExtensionPointName.create("com.intellij.postfixTemplate"); - protected PostfixTemplate(@NotNull String name, @NotNull String description, @NotNull String example) { this(name, "." + name, description, example); } @@ -71,12 +63,6 @@ public abstract class PostfixTemplate { return settings != null && settings.isPostfixTemplatesEnabled() && settings.isTemplateEnabled(this); } - @Nullable - public static PsiExpression getTopmostExpression(PsiElement context) { - PsiExpressionStatement statement = PsiTreeUtil.getNonStrictParentOfType(context, PsiExpressionStatement.class); - return statement != null ? PsiTreeUtil.getChildOfType(statement, PsiExpression.class) : null; - } - public abstract boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset); public abstract void expand(@NotNull PsiElement context, @NotNull Editor editor); diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateProvider.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateProvider.java new file mode 100644 index 000000000000..eeea9a19f62e --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateProvider.java @@ -0,0 +1,52 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.template.postfix.templates; + + +import com.intellij.openapi.editor.Editor; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NotNull; + +import java.util.Set; + +public interface PostfixTemplateProvider { + + /** + * Return all templates registered in the provider + */ + @NotNull + Set<PostfixTemplate> getTemplates(); + + /** + * Check symbol can separate template keys + */ + boolean isTerminalSymbol(char currentChar); + + /** + * Prepare original file content for template expanding + * Return context after transformation + */ + @NotNull + PsiElement preExpand(@NotNull Editor editor, @NotNull PsiElement context, int offset, @NotNull String key); + + /** + * Do some actions with the file content before check applicable. + * Return copyFile or another copy of file after processing + */ + @NotNull + PsiFile preCheck(@NotNull Editor editor, @NotNull PsiFile copyFile, int currentOffset); +} diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ReturnStatementPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ReturnStatementPostfixTemplate.java index 277a6f2c0d30..afc3236b8319 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ReturnStatementPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ReturnStatementPostfixTemplate.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInsight.template.postfix.templates; +import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; import com.intellij.openapi.editor.Editor; import com.intellij.psi.*; import org.jetbrains.annotations.NotNull; @@ -26,7 +27,7 @@ public class ReturnStatementPostfixTemplate extends NonVoidPostfixTemplate { @Override public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PsiExpression expr = getTopmostExpression(context); + PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); PsiElement parent = expr != null ? expr.getParent() : null; if (!(parent instanceof PsiExpressionStatement)) return; PsiElementFactory factory = JavaPsiFacade.getInstance(expr.getProject()).getElementFactory(); diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementPostfixTemplateBase.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementPostfixTemplateBase.java index 4449c551dbfc..8f26ec08fae0 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementPostfixTemplateBase.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementPostfixTemplateBase.java @@ -1,6 +1,22 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.codeInsight.template.postfix.templates; import com.intellij.codeInsight.CodeInsightUtilCore; +import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; @@ -17,7 +33,7 @@ public abstract class StatementPostfixTemplateBase extends PostfixTemplate { } protected void surroundWith(PsiElement context, Editor editor, String text) { - PsiExpression expr = getTopmostExpression(context); + PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); PsiElement parent = expr != null ? expr.getParent() : null; if (!(parent instanceof PsiExpressionStatement)) return; diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SwitchStatementPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SwitchStatementPostfixTemplate.java index 880c0455775b..20a7299af8ec 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SwitchStatementPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SwitchStatementPostfixTemplate.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInsight.template.postfix.templates; +import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; @@ -51,7 +52,7 @@ public class SwitchStatementPostfixTemplate extends StatementPostfixTemplateBase @Override public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - PsiExpression expr = getTopmostExpression(context); + PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); return expr != null && isSwitchCompatibleType(expr.getType(), context); } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SynchronizedStatementPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SynchronizedStatementPostfixTemplate.java index 044dadc81c8c..eb46ba9f0540 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SynchronizedStatementPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SynchronizedStatementPostfixTemplate.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInsight.template.postfix.templates; +import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.psi.PsiElement; @@ -30,7 +31,7 @@ public class SynchronizedStatementPostfixTemplate extends StatementPostfixTempla @Override public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - PsiExpression expression = getTopmostExpression(context); + PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context); PsiType type = expression != null ? expression.getType() : null; return type != null && !(type instanceof PsiPrimitiveType); } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ThrowExceptionPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ThrowExceptionPostfixTemplate.java index b1bb654d6dff..7b0aaa00f4c1 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ThrowExceptionPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ThrowExceptionPostfixTemplate.java @@ -29,7 +29,7 @@ public class ThrowExceptionPostfixTemplate extends PostfixTemplate { @Override public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - PsiExpression expression = getTopmostExpression(context); + PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context); return expression != null && PostfixTemplatesUtils.isThrowable(expression.getType()); } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/TryWithResourcesPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/TryWithResourcesPostfixTemplate.java new file mode 100644 index 000000000000..843c19e072c0 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/TryWithResourcesPostfixTemplate.java @@ -0,0 +1,110 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.template.postfix.templates; + +import com.intellij.codeInsight.ExceptionUtil; +import com.intellij.codeInsight.intention.impl.TypeExpression; +import com.intellij.codeInsight.template.Template; +import com.intellij.codeInsight.template.TemplateManager; +import com.intellij.codeInsight.template.impl.MacroCallNode; +import com.intellij.codeInsight.template.impl.TextExpression; +import com.intellij.codeInsight.template.macro.SuggestVariableNameMacro; +import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.intellij.psi.search.ProjectScope; +import com.intellij.psi.util.InheritanceUtil; +import com.intellij.psi.util.PsiUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.Collections; + + +public class TryWithResourcesPostfixTemplate extends PostfixTemplate { + protected TryWithResourcesPostfixTemplate() { + super("twr", "Description", "Example"); + } + + @Override + public boolean isApplicable(@NotNull PsiElement element, @NotNull Document copyDocument, int newOffset) { + if (!PsiUtil.isLanguageLevel7OrHigher(element)) return false; + + PsiExpression initializer = PostfixTemplatesUtils.getTopmostExpression(element); + + if (initializer == null) return false; + + final PsiType type = initializer.getType(); + if (!(type instanceof PsiClassType)) return false; + final PsiClass aClass = ((PsiClassType)type).resolve(); + Project project = element.getProject(); + final JavaPsiFacade facade = JavaPsiFacade.getInstance(project); + final PsiClass autoCloseable = facade.findClass(CommonClassNames.JAVA_LANG_AUTO_CLOSEABLE, ProjectScope.getLibrariesScope(project)); + if (!InheritanceUtil.isInheritorOrSelf(aClass, autoCloseable, true)) return false; + + return true; + } + + @Override + public void expand(@NotNull PsiElement context, @NotNull Editor editor) { + PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context); + assert expression != null; + + Project project = context.getProject(); + + editor.getDocument().deleteString(expression.getTextRange().getStartOffset(), expression.getTextRange().getEndOffset()); + + TemplateManager manager = TemplateManager.getInstance(project); + Template template = manager.createTemplate("", ""); + template.setToReformat(true); + template.addTextSegment("try ("); + MacroCallNode name = new MacroCallNode(new SuggestVariableNameMacro()); + + template.addVariable("type", new TypeExpression(project, new PsiType[]{expression.getType()}), false); + template.addTextSegment(" "); + template.addVariable("name", name, name, true); + template.addTextSegment(" = "); + template.addVariable("variable", new TextExpression(expression.getText()), false); + template.addTextSegment(") {\n"); + template.addEndVariable(); + template.addTextSegment("\n}"); + + Collection<PsiClassType> unhandled = getUnhandled(expression); + for (PsiClassType exception : unhandled) { + MacroCallNode variable = new MacroCallNode(new SuggestVariableNameMacro()); + template.addTextSegment("catch("); + template.addVariable("type " + exception.getClassName(), new TypeExpression(project, new PsiType[]{exception}), false); + template.addTextSegment(" "); + template.addVariable("name " + exception.getClassName(), variable, variable, false); + template.addTextSegment(") {}"); + } + + manager.startTemplate(editor, template); + } + + @NotNull + private static Collection<PsiClassType> getUnhandled(@NotNull PsiExpression expression) { + assert expression.getType() != null; + PsiMethod methodCloser = PsiUtil.getResourceCloserMethodForType((PsiClassType)expression.getType(), expression.getProject()); + PsiSubstitutor substitutor = PsiUtil.resolveGenericsClassInType(expression.getType()).getSubstitutor(); + + return methodCloser != null + ? ExceptionUtil.getUnhandledExceptions(methodCloser, expression, null, substitutor) + : Collections.<PsiClassType>emptyList(); + } +} diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/WhileStatementPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/WhileStatementPostfixTemplate.java index 03d91b2235af..4c856f7e8299 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/WhileStatementPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/WhileStatementPostfixTemplate.java @@ -1,5 +1,21 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.codeInsight.template.postfix.templates; +import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; import com.intellij.openapi.editor.Editor; import com.intellij.psi.*; import org.jetbrains.annotations.NotNull; @@ -11,7 +27,7 @@ public class WhileStatementPostfixTemplate extends BooleanPostfixTemplate { @Override public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PsiExpression expression = getTopmostExpression(context); + PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context); assert expression != null; PsiElementFactory factory = JavaPsiFacade.getElementFactory(context.getProject()); diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/Aliases.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/Aliases.java deleted file mode 100644 index 3de07c310f50..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/Aliases.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.intellij.codeInsight.template.postfix.util; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @author ignatov - */ -@Target(value = ElementType.TYPE) -@Retention(value = RetentionPolicy.RUNTIME) -public @interface Aliases { - String[] value(); -} diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/PostfixTemplatesUtils.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/PostfixTemplatesUtils.java index 370c986c5f48..7b92ffdb1ae0 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/PostfixTemplatesUtils.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/PostfixTemplatesUtils.java @@ -17,12 +17,12 @@ package com.intellij.codeInsight.template.postfix.util; import com.intellij.codeInsight.generation.surroundWith.JavaExpressionSurrounder; import com.intellij.codeInsight.generation.surroundWith.JavaWithIfExpressionSurrounder; -import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.util.InheritanceUtil; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.util.CommonRefactoringUtil; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; @@ -45,7 +45,7 @@ public abstract class PostfixTemplatesUtils { } public static void createStatement(@NotNull PsiElement context, @NotNull Editor editor, @NotNull String prefix, @NotNull String suffix, int offset) { - PsiExpression expr = PostfixTemplate.getTopmostExpression(context); + PsiExpression expr = getTopmostExpression(context); PsiElement parent = expr != null ? expr.getParent() : null; assert parent instanceof PsiStatement; PsiElementFactory factory = JavaPsiFacade.getInstance(context.getProject()).getElementFactory(); @@ -121,5 +121,11 @@ public abstract class PostfixTemplatesUtils { } return null; } + + @Nullable + public static PsiExpression getTopmostExpression(PsiElement context) { + PsiExpressionStatement statement = PsiTreeUtil.getNonStrictParentOfType(context, PsiExpressionStatement.class); + return statement != null ? PsiTreeUtil.getChildOfType(statement, PsiExpression.class) : null; + } } diff --git a/java/java-impl/src/com/intellij/ide/fileTemplates/JavaCreateFromTemplateHandler.java b/java/java-impl/src/com/intellij/ide/fileTemplates/JavaCreateFromTemplateHandler.java index 26e4adfa0bbb..f511eac9320d 100644 --- a/java/java-impl/src/com/intellij/ide/fileTemplates/JavaCreateFromTemplateHandler.java +++ b/java/java-impl/src/com/intellij/ide/fileTemplates/JavaCreateFromTemplateHandler.java @@ -26,6 +26,7 @@ import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.impl.file.JavaDirectoryServiceImpl; import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; import java.util.Map; @@ -100,8 +101,9 @@ public class JavaCreateFromTemplateHandler implements CreateFromTemplateHandler return fileType.equals(StdFileTypes.JAVA) && !FileTemplateUtil.INTERNAL_PACKAGE_INFO_TEMPLATE_NAME.equals(template.getName()); } + @NotNull public PsiElement createFromTemplate(final Project project, final PsiDirectory directory, final String fileName, FileTemplate template, - String templateText, Map<String, Object> props) throws IncorrectOperationException { + String templateText, @NotNull Map<String, Object> props) throws IncorrectOperationException { String extension = template.getExtension(); PsiElement result = createClassOrInterface(project, directory, templateText, template.isReformatCode(), extension); hackAwayEmptyPackage((PsiJavaFile)result.getContainingFile(), template, props); diff --git a/java/java-impl/src/com/intellij/ide/hierarchy/method/MethodHierarchyNodeDescriptor.java b/java/java-impl/src/com/intellij/ide/hierarchy/method/MethodHierarchyNodeDescriptor.java index 61e530339ffa..dbdcff0f798b 100644 --- a/java/java-impl/src/com/intellij/ide/hierarchy/method/MethodHierarchyNodeDescriptor.java +++ b/java/java-impl/src/com/intellij/ide/hierarchy/method/MethodHierarchyNodeDescriptor.java @@ -52,7 +52,7 @@ public final class MethodHierarchyNodeDescriptor extends HierarchyNodeDescriptor myTreeStructure = treeStructure; } - private PsiMethod getMethod(final PsiClass aClass, final boolean checkBases) { + PsiMethod getMethod(final PsiClass aClass, final boolean checkBases) { return MethodHierarchyUtil.findBaseMethodInClass(myTreeStructure.getBaseMethod(), aClass, checkBases); } diff --git a/java/java-impl/src/com/intellij/ide/hierarchy/method/MethodHierarchyTreeStructure.java b/java/java-impl/src/com/intellij/ide/hierarchy/method/MethodHierarchyTreeStructure.java index 7a5e86953689..922fc2d85644 100644 --- a/java/java-impl/src/com/intellij/ide/hierarchy/method/MethodHierarchyTreeStructure.java +++ b/java/java-impl/src/com/intellij/ide/hierarchy/method/MethodHierarchyTreeStructure.java @@ -172,13 +172,16 @@ public final class MethodHierarchyTreeStructure extends HierarchyTreeStructure { descriptors.add(d); } - FunctionalExpressionSearch.search(getBaseMethod()).forEach(new Processor<PsiFunctionalExpression>() { - @Override - public boolean process(PsiFunctionalExpression expression) { - descriptors.add(new MethodHierarchyNodeDescriptor(myProject, descriptor, expression, false, MethodHierarchyTreeStructure.this)); - return true; - } - }); + final PsiMethod existingMethod = ((MethodHierarchyNodeDescriptor)descriptor).getMethod(psiClass, false); + if (existingMethod != null) { + FunctionalExpressionSearch.search(existingMethod).forEach(new Processor<PsiFunctionalExpression>() { + @Override + public boolean process(PsiFunctionalExpression expression) { + descriptors.add(new MethodHierarchyNodeDescriptor(myProject, descriptor, expression, false, MethodHierarchyTreeStructure.this)); + return true; + } + }); + } return descriptors.toArray(new HierarchyNodeDescriptor[descriptors.size()]); } diff --git a/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java b/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java index 6a267f692ab0..56f376ffbf06 100644 --- a/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java +++ b/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java @@ -34,7 +34,6 @@ import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.*; -import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; @@ -56,8 +55,10 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; /** * @author Maxim.Mossienko @@ -591,13 +592,16 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext if (classUrls != null) { urls = ContainerUtil.newSmartList(); - String rawSignature = formatMethodSignature(method, true); - for (String classUrl : classUrls) { - urls.add(classUrl + "#" + rawSignature); - } + final boolean useJava8Format = PsiUtil.isLanguageLevel8OrHigher(method); + + final Set<String> signatures = new LinkedHashSet<String>(); + signatures.add(formatMethodSignature(method, true, useJava8Format)); + signatures.add(formatMethodSignature(method, false, useJava8Format)); + + signatures.add(formatMethodSignature(method, true, !useJava8Format)); + signatures.add(formatMethodSignature(method, false, !useJava8Format)); - String signature = formatMethodSignature(method, false); - if (Comparing.compare(rawSignature, signature) != 0) { + for (String signature : signatures) { for (String classUrl : classUrls) { urls.add(classUrl + "#" + signature); } @@ -626,7 +630,7 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext } } - private static String formatMethodSignature(PsiMethod method, boolean raw) { + private static String formatMethodSignature(PsiMethod method, boolean raw, boolean java8Format) { int options = PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS; int parameterOptions = PsiFormatUtilBase.SHOW_TYPE | PsiFormatUtilBase.SHOW_FQ_CLASS_NAMES; if (raw) { @@ -636,7 +640,7 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext String signature = PsiFormatUtil.formatMethod(method, PsiSubstitutor.EMPTY, options, parameterOptions, 999); - if (PsiUtil.isLanguageLevel8OrHigher(method)) { + if (java8Format) { signature = signature.replaceAll("\\(|\\)|, ", "-").replaceAll("\\[\\]", ":A"); } diff --git a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java index 2aa495c42694..f3d6575e9fd9 100644 --- a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java +++ b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -98,7 +98,7 @@ public class JavaSdkImpl extends JavaSdk { return "http://docs.oracle.com/javase/7/docs/api/"; } if (version == JavaSdkVersion.JDK_1_8) { - return "http://download.java.net/jdk8/docs/api/"; + return "http://docs.oracle.com/javase/8/docs/api"; } return null; } @@ -416,19 +416,6 @@ public class JavaSdkImpl extends JavaSdk { } @Override - @NotNull - public String getComponentName() { - return getName(); - } - - @Override - public void initComponent() { } - - @Override - public void disposeComponent() { - } - - @Override public int compareTo(@NotNull String versionString, @NotNull String versionNumber) { return getVersionNumber(versionString).compareTo(versionNumber); } diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java index 9ade1c2a4495..0770a04f4dce 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -766,7 +766,7 @@ public class ImportHelper{ continue; } if (reference instanceof PsiJavaCodeReferenceElementImpl - && ((PsiJavaCodeReferenceElementImpl)reference).getKind() == PsiJavaCodeReferenceElementImpl.CLASS_IN_QUALIFIED_NEW_KIND) { + && ((PsiJavaCodeReferenceElementImpl)reference).getKind(((PsiJavaCodeReferenceElementImpl)reference).getContainingFile()) == PsiJavaCodeReferenceElementImpl.CLASS_IN_QUALIFIED_NEW_KIND) { continue; } } @@ -774,7 +774,7 @@ public class ImportHelper{ final JavaResolveResult resolveResult = javaReference.advancedResolve(true); PsiElement refElement = resolveResult.getElement(); if (refElement == null && referenceElement != null) { - refElement = ResolveClassUtil.resolveClass(referenceElement); // might be uncomplete code + refElement = ResolveClassUtil.resolveClass(referenceElement, referenceElement.getContainingFile()); // might be uncomplete code } if (refElement == null) continue; diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java index b151628781d7..844ef00880ae 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java @@ -27,14 +27,11 @@ import com.intellij.psi.impl.CheckUtil; import com.intellij.psi.impl.source.SourceTreeToPsiMap; import com.intellij.psi.impl.source.jsp.jspJava.JspxImportStatement; import com.intellij.psi.statistics.JavaStatisticsManager; -import com.intellij.psi.util.PsiElementFilter; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.util.PsiUtil; -import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.psi.util.*; import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; -import com.intellij.psi.util.FileTypeUtils; import gnu.trove.THashSet; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -309,7 +306,7 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager { return suggestVariableNameByType(type, variableKind, correctKeywords, false); } - private String[] suggestVariableNameByType(PsiType type, final VariableKind variableKind, boolean correctKeywords, boolean skipIndices) { + private String[] suggestVariableNameByType(final PsiType type, final VariableKind variableKind, final boolean correctKeywords, boolean skipIndices) { String longTypeName = skipIndices ? type.getCanonicalText():getLongTypeName(type); CodeStyleSettings.TypeToNameMap map = getMapByVariableKind(variableKind); if (map != null && longTypeName != null) { @@ -322,7 +319,7 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager { } } - Collection<String> suggestions = new LinkedHashSet<String>(); + final Collection<String> suggestions = new LinkedHashSet<String>(); if (!skipIndices) { suggestNamesForCollectionInheritors(type, variableKind, suggestions, correctKeywords); @@ -336,6 +333,21 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager { ContainerUtil.addAll(suggestions, getSuggestionsByName(typeName, variableKind, type instanceof PsiArrayType, correctKeywords)); } + if (!skipIndices && type instanceof PsiClassType) { + final PsiClass psiClass = ((PsiClassType)type).resolve(); + if (psiClass != null && psiClass.getContainingClass() != null) { + InheritanceUtil.processSupers(psiClass, false, new Processor<PsiClass>() { + @Override + public boolean process(PsiClass superClass) { + if (PsiTreeUtil.isAncestor(superClass, psiClass, true)) { + ContainerUtil.addAll(suggestions, getSuggestionsByName(superClass.getName(), variableKind, false, correctKeywords)); + } + return false; + } + }); + } + } + return ArrayUtil.toStringArray(suggestions); } diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaReferenceAdjuster.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaReferenceAdjuster.java index 42d3098b7b07..3d1e1c01c586 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaReferenceAdjuster.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaReferenceAdjuster.java @@ -55,7 +55,8 @@ public class JavaReferenceAdjuster implements ReferenceAdjuster { boolean rightKind = true; if (elementType == JavaElementType.JAVA_CODE_REFERENCE) { - int kind = ((PsiJavaCodeReferenceElementImpl)element).getKind(); + PsiJavaCodeReferenceElementImpl impl = (PsiJavaCodeReferenceElementImpl)element; + int kind = impl.getKind(impl.getContainingFile()); rightKind = kind == PsiJavaCodeReferenceElementImpl.CLASS_NAME_KIND || kind == PsiJavaCodeReferenceElementImpl.CLASS_OR_PACKAGE_NAME_KIND; } diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReference.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReference.java index 71e40e5b0ac6..a0243dfc241a 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReference.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReference.java @@ -268,10 +268,11 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer return JavaClassReferenceProvider.EXTEND_CLASS_NAMES.getValue(getOptions()); } - private LookupElement[] processPackage(final PsiPackage aPackage) { + @NotNull + private LookupElement[] processPackage(@NotNull PsiPackage aPackage) { final ArrayList<LookupElement> list = ContainerUtil.newArrayList(); final int startOffset = StringUtil.isEmpty(aPackage.getName()) ? 0 : aPackage.getQualifiedName().length() + 1; - final GlobalSearchScope scope = getScope(); + final GlobalSearchScope scope = getScope(getElement().getContainingFile()); for (final PsiPackage subPackage : aPackage.getSubPackages(scope)) { final String shortName = subPackage.getQualifiedName().substring(startOffset); if (JavaPsiFacade.getInstance(subPackage.getProject()).getNameHelper().isIdentifier(shortName)) { @@ -355,7 +356,8 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer return (JavaResolveResult) resolveCache.resolveWithCaching(this, MyResolver.INSTANCE, false, false,file)[0]; } - private JavaResolveResult doAdvancedResolve() { + @NotNull + private JavaResolveResult doAdvancedResolve(@NotNull PsiFile containingFile) { final PsiElement psiElement = getElement(); if (!psiElement.isValid()) return JavaResolveResult.EMPTY; @@ -366,7 +368,9 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer if (context instanceof PsiClass) { if (isStaticClassReference(elementText, false)) { final PsiClass psiClass = ((PsiClass)context).findInnerClassByName(getCanonicalText(), false); - if (psiClass != null) return new ClassCandidateInfo(psiClass, PsiSubstitutor.EMPTY, false, psiElement); + if (psiClass != null) { + return new ClassCandidateInfo(psiClass, PsiSubstitutor.EMPTY, false, psiElement); + } PsiElement member = doResolveMember((PsiClass)context, myText); return member == null ? JavaResolveResult.EMPTY : new CandidateInfo(member, PsiSubstitutor.EMPTY, false, false, psiElement); } @@ -382,18 +386,18 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer if (!qName.contains(".")) { final String defaultPackage = JavaClassReferenceProvider.DEFAULT_PACKAGE.getValue(getOptions()); if (StringUtil.isNotEmpty(defaultPackage)) { - final JavaResolveResult resolveResult = advancedResolveInner(psiElement, defaultPackage + "." + qName); + final JavaResolveResult resolveResult = advancedResolveInner(psiElement, defaultPackage + "." + qName, containingFile); if (resolveResult != JavaResolveResult.EMPTY) { return resolveResult; } } } - return advancedResolveInner(psiElement, qName); + return advancedResolveInner(psiElement, qName, containingFile); } - private JavaResolveResult advancedResolveInner(final PsiElement psiElement, final String qName) { - final PsiManager manager = psiElement.getManager(); - final GlobalSearchScope scope = getScope(); + private JavaResolveResult advancedResolveInner(@NotNull PsiElement psiElement, @NotNull String qName, @NotNull PsiFile containingFile) { + final PsiManager manager = containingFile.getManager(); + final GlobalSearchScope scope = getScope(containingFile); if (myIndex == myJavaClassReferenceSet.getReferences().length - 1) { final PsiClass aClass = JavaPsiFacade.getInstance(manager.getProject()).findClass(qName, scope); if (aClass != null) { @@ -413,8 +417,6 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer resolveResult = resolveMember(qName, manager, getElement().getResolveScope()); } if (resolveResult == null) { - PsiFile containingFile = psiElement.getContainingFile(); - if (containingFile instanceof PsiJavaFile) { if (containingFile instanceof ServerPageFile) { containingFile = containingFile.getViewProvider().getPsi(JavaLanguage.INSTANCE); @@ -448,12 +450,12 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer : JavaResolveResult.EMPTY; } - private GlobalSearchScope getScope() { - Project project = getElement().getProject(); + private GlobalSearchScope getScope(@NotNull PsiFile containingFile) { + Project project = containingFile.getProject(); GlobalSearchScope scope = myJavaClassReferenceSet.getProvider().getScope(project); if (scope == null) { - Module module = ModuleUtilCore.findModuleForPsiElement(getElement()); - return module != null ? module.getModuleWithDependenciesAndLibrariesScope(true) : GlobalSearchScope.allScope(project); + Module module = ModuleUtilCore.findModuleForPsiElement(containingFile); + return module == null ? GlobalSearchScope.allScope(project) : module.getModuleWithDependenciesAndLibrariesScope(true); } return scope; } @@ -472,7 +474,7 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer } @Nullable - private List<? extends LocalQuickFix> registerFixes(final HighlightInfo info) { + private List<? extends LocalQuickFix> registerFixes(HighlightInfo info) { final List<LocalQuickFix> list = OrderEntryFix.registerFixes(new QuickFixActionRegistrarImpl(info), this); @@ -498,7 +500,7 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer final TextRange range = new TextRange(references[0].getRangeInElement().getStartOffset(), getRangeInElement().getEndOffset()); final String qualifiedName = range.substring(getElement().getText()); - final CreateClassOrPackageFix action = CreateClassOrPackageFix.createFix(qualifiedName, getScope(), getElement(), contextPackage, + final CreateClassOrPackageFix action = CreateClassOrPackageFix.createFix(qualifiedName, getScope(getElement().getContainingFile()), getElement(), contextPackage, kind, extendClass, templateName); if (action != null) { QuickFixAction.registerQuickFixAction(info, action); @@ -591,13 +593,13 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer return myJavaClassReferenceSet.getUnresolvedMessagePattern(myIndex); } - private static class MyResolver implements ResolveCache.PolyVariantResolver<JavaClassReference> { + private static class MyResolver implements ResolveCache.PolyVariantContextResolver<JavaClassReference> { private static final MyResolver INSTANCE = new MyResolver(); @NotNull @Override - public JavaResolveResult[] resolve(@NotNull JavaClassReference javaClassReference, boolean incompleteCode) { - return new JavaResolveResult[]{javaClassReference.doAdvancedResolve()}; + public ResolveResult[] resolve(@NotNull JavaClassReference ref, @NotNull PsiFile containingFile, boolean incompleteCode) { + return new JavaResolveResult[]{ref.doAdvancedResolve(containingFile)}; } } diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaTreeCopyHandler.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaTreeCopyHandler.java index 283e8578e146..a0234777aa86 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaTreeCopyHandler.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaTreeCopyHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -200,7 +200,7 @@ public class JavaTreeCopyHandler implements TreeCopyHandler { } } else if (original.getElementType() == JavaElementType.JAVA_CODE_REFERENCE) { - switch (((PsiJavaCodeReferenceElementImpl)original).getKind()) { + switch (((PsiJavaCodeReferenceElementImpl)original).getKind(((PsiJavaCodeReferenceElementImpl)original).getContainingFile())) { case PsiJavaCodeReferenceElementImpl.CLASS_NAME_KIND: case PsiJavaCodeReferenceElementImpl.CLASS_OR_PACKAGE_NAME_KIND: case PsiJavaCodeReferenceElementImpl.CLASS_IN_QUALIFIED_NEW_KIND: |