1868 codeCompletionForMessage:node into:actionBlock |
1868 codeCompletionForMessage:node into:actionBlock |
1869 "find good completions for a message selector in a message-send node" |
1869 "find good completions for a message selector in a message-send node" |
1870 |
1870 |
1871 |selector lcSelector bestSelectors parentSelector newParentSelector bestSelectors2 bestWithParenthesis allBest numArgs |
1871 |selector lcSelector bestSelectors parentSelector newParentSelector bestSelectors2 bestWithParenthesis allBest numArgs |
1872 newParts nSelParts oldLen newLen selectorParts |
1872 newParts nSelParts oldLen newLen selectorParts |
1873 findBest parentNode nodeReceiver "selectorsSentInCode" selectorsImplementedInClass |
1873 parentNode nodeReceiver "selectorsSentInCode" selectorsImplementedInClass |
1874 editAction parentNodeClassIfKnown |
1874 editAction parentNodeClassIfKnown |
1875 receiverNodeClassIfKnown |
1875 receiverNodeClassIfKnown |
1876 offerParenthisationAroundNode parenthesisAroundIndex parentNodeToParenthesize |
1876 offerParenthisationAroundNode parenthesisAroundIndex parentNodeToParenthesize |
1877 offerValueInsertion valueToInsert valueToInsertIndex valueInfo |
1877 offerValueInsertion valueToInsert valueToInsertIndex valueInfo |
1878 classesFromAssignmentsToReceiver otherMessagesToReceiver |
1878 classesFromAssignmentsToReceiver otherMessagesToReceiver |
1879 canParenthesize classesOfReceiver| |
1879 canParenthesize classesOfReceiver| |
1880 |
1880 |
1881 "/ Transcript show:'node '; show:node; show:' ; '. |
1881 Verbose == true ifTrue:[ |
1882 "/ Transcript show:'msg in '; show:methodOrNil; show:' / '; showCR:classOrNil. |
1882 Transcript show:'node '; show:node; show:' ; '. |
1883 |
1883 Transcript show:'msg in '; show:methodOrNil; show:' / '; showCR:classOrNil. |
|
1884 ]. |
|
1885 |
1884 offerParenthisationAroundNode := nil. |
1886 offerParenthisationAroundNode := nil. |
1885 offerValueInsertion := false. |
1887 offerValueInsertion := false. |
1886 |
|
1887 "/ node at:1 |
|
1888 |
|
1889 findBest := |
|
1890 [:node :selector | |
|
1891 |srchClasses bestSelectors bestPrefixes |
|
1892 allMessagesSentToVariable classesImplementingAllMessages| |
|
1893 |
|
1894 srchClasses := node==nodeReceiver |
|
1895 ifTrue:[classesOfReceiver] |
|
1896 ifFalse:[self classesOfNode:node]. |
|
1897 |
|
1898 srchClasses isEmptyOrNil ifTrue:[ |
|
1899 node isVariable ifTrue:[ |
|
1900 allMessagesSentToVariable := Set new. |
|
1901 rememberedNodes do:[:eachNode | |
|
1902 eachNode allMessageNodesDo:[:eachMessage | |
|
1903 |msgReceiver msgSelector| |
|
1904 |
|
1905 (msgReceiver := eachMessage receiver) isVariable ifTrue:[ |
|
1906 msgReceiver name = node name ifTrue:[ |
|
1907 (msgSelector := eachMessage selector) ~= selector ifTrue:[ |
|
1908 allMessagesSentToVariable add:msgSelector |
|
1909 ] |
|
1910 ] |
|
1911 ] |
|
1912 ] |
|
1913 ]. |
|
1914 allMessagesSentToVariable notEmpty ifTrue:[ |
|
1915 "/ consider classes which implement all those messages. |
|
1916 classesImplementingAllMessages := Smalltalk allImplementorsOf:(allMessagesSentToVariable first). |
|
1917 allMessagesSentToVariable do:[:eachSelector | |
|
1918 classesImplementingAllMessages := classesImplementingAllMessages |
|
1919 select:[:cls | cls implements:eachSelector]. |
|
1920 ]. |
|
1921 srchClasses := classesImplementingAllMessages. |
|
1922 ]. |
|
1923 ]. |
|
1924 ]. |
|
1925 bestSelectors := Set new. |
|
1926 srchClasses isEmptyOrNil ifTrue:[ |
|
1927 bestSelectors addAll:( Parser findBest:50 selectorsFor:selector in:nil forCompletion:true ). |
|
1928 ] ifFalse:[ |
|
1929 srchClasses do:[:srchClass | |
|
1930 |bestForThisClass| |
|
1931 |
|
1932 bestForThisClass := Parser findBest:50 selectorsFor:selector in:srchClass forCompletion:true. |
|
1933 bestForThisClass := self |
|
1934 withoutSelectorsUnlikelyFor:srchClass |
|
1935 from:bestForThisClass |
|
1936 forPartial:selector. |
|
1937 bestSelectors addAll:bestForThisClass. |
|
1938 ]. |
|
1939 ]. |
|
1940 "/ remove the already typed-in selector itself, in case. |
|
1941 bestSelectors remove:selector ifAbsent:[]. |
|
1942 bestSelectors := bestSelectors asOrderedCollection. |
|
1943 bestSelectors |
|
1944 ]. |
|
1945 |
1888 |
1946 selector := node selector. |
1889 selector := node selector. |
1947 lcSelector := selector asLowercase. |
1890 lcSelector := selector asLowercase. |
1948 parentNode := node parent. |
1891 parentNode := node parent. |
1949 nodeReceiver := node receiver. |
1892 nodeReceiver := node receiver. |
1950 nodeReceiver notNil ifTrue:[ |
1893 nodeReceiver notNil ifTrue:[ |
1951 classesOfReceiver := self classesOfNode:nodeReceiver. |
1894 classesOfReceiver := self classesOfNode:nodeReceiver. |
1952 ]. |
1895 ]. |
1953 Transcript show:node; show:' -> '; showCR:classesOfReceiver. |
1896 Verbose == true ifTrue:[ |
1954 ( node isVariable and:[node name = 'self']) ifTrue:[self halt]. |
1897 Transcript show:node; show:' -> '; showCR:classesOfReceiver. |
1955 |
1898 ( node isVariable and:[node name = 'self']) ifTrue:[self halt]. |
|
1899 ]. |
|
1900 |
1956 "/ if there is already space before the cursor, and the parent node is not a message, |
1901 "/ if there is already space before the cursor, and the parent node is not a message, |
1957 "/ do not attempt to complete the current message. |
1902 "/ do not attempt to complete the current message. |
1958 "/ If it is a message, we will look for parent-message completion also below (best2 stuff) |
1903 "/ If it is a message, we will look for parent-message completion also below (best2 stuff) |
1959 (codeView characterBeforeCursor ? $ ) isSeparator ifTrue:[ |
1904 (codeView characterBeforeCursor ? $ ) isSeparator ifTrue:[ |
1960 selector isKeyword ifFalse:[ |
1905 selector isKeyword ifFalse:[ |
2095 (selector isUnarySelector and:[ parentNode notNil and:[ parentNode isMessage ]]) ifTrue:[ |
2044 (selector isUnarySelector and:[ parentNode notNil and:[ parentNode isMessage ]]) ifTrue:[ |
2096 (parentSelector := parentNode selector) isKeyword ifTrue:[ |
2045 (parentSelector := parentNode selector) isKeyword ifTrue:[ |
2097 "/ if its a unary message AND the parent is a keyword node, look for parent completion too. |
2046 "/ if its a unary message AND the parent is a keyword node, look for parent completion too. |
2098 "/ i.e. look if there is a longer keyword possible |
2047 "/ i.e. look if there is a longer keyword possible |
2099 newParentSelector := parentSelector,selector. |
2048 newParentSelector := parentSelector,selector. |
2100 bestSelectors2 := findBest value:(parentNode receiver) value:newParentSelector. |
2049 bestSelectors2 := self |
|
2050 findBest:(parentNode receiver) for:newParentSelector |
|
2051 inClasses:(self classesOfNode:parentNode receiver). |
2101 bestSelectors2 := bestSelectors2 select:[:sel | sel isKeyword and:[ sel startsWith:parentSelector]]. |
2052 bestSelectors2 := bestSelectors2 select:[:sel | sel isKeyword and:[ sel startsWith:parentSelector]]. |
2102 bestSelectors2 := bestSelectors2 asOrderedCollection sort:[:a :b | a size < b size]. |
2053 bestSelectors2 := bestSelectors2 asOrderedCollection sort:[:a :b | a size < b size]. |
2103 bestSelectors := bestSelectors reject:[:sel | bestSelectors2 includes:sel]. |
2054 bestSelectors := bestSelectors reject:[:sel | bestSelectors2 includes:sel]. |
2104 |
2055 |
2105 "/ if the parent has a valid selector, offer parenthization |
2056 "/ if the parent has a valid selector, offer parenthization |
3772 ^ self editActionToReplaceCodeFrom:node start to:node stop byWordIn:suggestions |
3725 ^ self editActionToReplaceCodeFrom:node start to:node stop byWordIn:suggestions |
3773 |
3726 |
3774 "Created: / 01-05-2016 / 18:44:09 / cg" |
3727 "Created: / 01-05-2016 / 18:44:09 / cg" |
3775 ! |
3728 ! |
3776 |
3729 |
|
3730 findBest:node for:selector inClasses:srchClassesArg |
|
3731 |srchClasses bestSelectors |
|
3732 allMessagesSentToVariable classesImplementingAllMessages| |
|
3733 |
|
3734 srchClasses := srchClassesArg. |
|
3735 Verbose == true ifTrue:[ |
|
3736 Transcript show:'node: '; showCR:node. |
|
3737 Transcript show:'srchClasses: '; showCR:srchClasses. |
|
3738 ]. |
|
3739 |
|
3740 srchClasses isEmptyOrNil ifTrue:[ |
|
3741 node isVariable ifTrue:[ |
|
3742 allMessagesSentToVariable := Set new. |
|
3743 rememberedNodes do:[:eachNode | |
|
3744 eachNode allMessageNodesDo:[:eachMessage | |
|
3745 |msgReceiver msgSelector| |
|
3746 |
|
3747 (msgReceiver := eachMessage receiver) isVariable ifTrue:[ |
|
3748 msgReceiver name = node name ifTrue:[ |
|
3749 (msgSelector := eachMessage selector) ~= selector ifTrue:[ |
|
3750 allMessagesSentToVariable add:msgSelector |
|
3751 ] |
|
3752 ] |
|
3753 ] |
|
3754 ] |
|
3755 ]. |
|
3756 allMessagesSentToVariable notEmpty ifTrue:[ |
|
3757 "/ consider classes which implement all those messages. |
|
3758 classesImplementingAllMessages := Smalltalk allImplementorsOf:(allMessagesSentToVariable first). |
|
3759 allMessagesSentToVariable do:[:eachSelector | |
|
3760 classesImplementingAllMessages := classesImplementingAllMessages |
|
3761 select:[:cls | cls implements:eachSelector]. |
|
3762 ]. |
|
3763 srchClasses := classesImplementingAllMessages. |
|
3764 ]. |
|
3765 ]. |
|
3766 ]. |
|
3767 bestSelectors := Set new. |
|
3768 srchClasses isEmptyOrNil ifTrue:[ |
|
3769 bestSelectors addAll:( Parser findBest:50 selectorsFor:selector in:nil forCompletion:true ). |
|
3770 Verbose == true ifTrue:[ |
|
3771 Transcript show:'bestSelectors (1): '; showCR:bestSelectors. |
|
3772 ]. |
|
3773 ] ifFalse:[ |
|
3774 srchClasses do:[:srchClass | |
|
3775 |bestForThisClass| |
|
3776 |
|
3777 bestForThisClass := Parser findBest:50 selectorsFor:selector in:srchClass forCompletion:true. |
|
3778 bestForThisClass := self |
|
3779 withoutSelectorsUnlikelyFor:srchClass |
|
3780 from:bestForThisClass |
|
3781 forPartial:selector. |
|
3782 Verbose == true ifTrue:[ |
|
3783 Transcript show:'bestSelectors (2): '; showCR:bestForThisClass. |
|
3784 ]. |
|
3785 bestSelectors addAll:bestForThisClass. |
|
3786 ]. |
|
3787 ]. |
|
3788 "/ remove the already typed-in selector itself, in case. |
|
3789 bestSelectors remove:selector ifAbsent:[]. |
|
3790 bestSelectors := bestSelectors asOrderedCollection. |
|
3791 ^ bestSelectors |
|
3792 ! |
|
3793 |
3777 findNodeForInterval:interval in:source |
3794 findNodeForInterval:interval in:source |
3778 |tree node| |
3795 |tree node| |
3779 |
3796 |
3780 interval isEmpty ifTrue: [^ nil]. |
3797 interval isEmpty ifTrue: [^ nil]. |
3781 RBParser isNil ifTrue: [^ nil]. |
3798 RBParser isNil ifTrue: [^ nil]. |
4599 found in object, but only make sense for variable objects or those which do |
4616 found in object, but only make sense for variable objects or those which do |
4600 implement at:put: themself. |
4617 implement at:put: themself. |
4601 I have currently no better idea than hardcoding stuff I found irritating..." |
4618 I have currently no better idea than hardcoding stuff I found irritating..." |
4602 |
4619 |
4603 |selectors noNilChecks noIsXXXChecks noNoXXXChecks noBecome |
4620 |selectors noNilChecks noIsXXXChecks noNoXXXChecks noBecome |
4604 noIndexedSetters noIndexedGetters noSizeQueries| |
4621 noIndexedSetters noIndexedGetters noSizeQueries docSelectors| |
4605 |
4622 |
4606 aClass isNil ifTrue:[ ^ selectorsArg ]. |
4623 aClass isNil ifTrue:[ ^ selectorsArg ]. |
4607 |
4624 |
4608 noNilChecks := noIsXXXChecks := noNoXXXChecks := noBecome := false. |
4625 noNilChecks := noIsXXXChecks := noNoXXXChecks := noBecome := false. |
4609 noIndexedSetters := noIndexedGetters := noSizeQueries := false. |
4626 noIndexedSetters := noIndexedGetters := noSizeQueries := false. |
4610 |
4627 |
4611 selectors := (selectorsArg ? #()) asOrderedCollection. |
4628 selectors := (selectorsArg ? #()) asOrderedCollection. |
4612 |
4629 |
4613 self tracePoint:#cg message:aClass. |
4630 self tracePoint:#cg message:aClass. |
4614 |
4631 |
|
4632 aClass isMeta ifTrue:[ |
|
4633 docSelectors := #(copyright documentation examples |
|
4634 version version_CVS version_SVN version_HG). |
|
4635 selectors := selectors reject:[:sel | docSelectors includes:sel]. |
|
4636 ]. |
|
4637 |
4615 "/ actually meaning booleans here |
4638 "/ actually meaning booleans here |
4616 (aClass == True or:[aClass == False]) ifTrue:[ |
4639 (aClass == True or:[aClass == False]) ifTrue:[ |
4617 noNilChecks := noBecome := true. |
4640 noNilChecks := noBecome := true. |
4618 (partialSelector startsWith:'is') ifFalse:[ noIsXXXChecks := true ]. |
4641 (partialSelector startsWith:'is') ifFalse:[ noIsXXXChecks := true ]. |
4619 (partialSelector startsWith:'no') ifFalse:[ noNoXXXChecks := true ]. |
4642 (partialSelector startsWith:'no') ifFalse:[ noNoXXXChecks := true ]. |