1701 |
1701 |
1702 "Created: / 10-11-2006 / 14:00:53 / cg" |
1702 "Created: / 10-11-2006 / 14:00:53 / cg" |
1703 ! |
1703 ! |
1704 |
1704 |
1705 classOfNode:aNode |
1705 classOfNode:aNode |
1706 "when showing possible completions for a message, |
1706 "returns the class of a receiver, if it is well-known. |
|
1707 Otherwise nil (either unknown, or multiple possibilities) |
|
1708 When showing possible completions for a message, |
1707 it is a good idea to know what the kind receiver is." |
1709 it is a good idea to know what the kind receiver is." |
1708 |
1710 |
1709 | nm nodeVal receiverClass nodeSelector nodeReceiver mthd| |
1711 | classes | |
|
1712 |
|
1713 classes := self classesOfNode:aNode. |
|
1714 classes size == 1 ifTrue:[ |
|
1715 ^ classes anElement |
|
1716 ]. |
|
1717 ^ nil |
|
1718 ! |
|
1719 |
|
1720 classesOfInstVarNamed:varName inClass:aClass |
|
1721 |setOfTypes instIndex| |
|
1722 |
|
1723 setOfTypes := IdentitySet new. |
|
1724 instIndex := aClass instVarIndexFor:varName. |
|
1725 |
|
1726 "/ look for instances |
|
1727 aClass allSubInstancesDo:[:i | |
|
1728 |varClass| |
|
1729 varClass := (i instVarAt:instIndex) class. |
|
1730 setOfTypes add:varClass. |
|
1731 ]. |
|
1732 |
|
1733 "/ look for assignments in code |
|
1734 aClass withAllSubclassesDo:[:eachClass | |
|
1735 eachClass methodDictionary do:[:m | |
|
1736 |tree code visitor| |
|
1737 |
|
1738 "/ quick check |
|
1739 code := m source. |
|
1740 (code notNil and:[code includesString:varName]) ifTrue:[ |
|
1741 tree := Parser parse:code class:eachClass. |
|
1742 (tree notNil and:[tree ~~ #Error]) ifTrue:[ |
|
1743 visitor := PluggableParseNodeVisitor new. |
|
1744 visitor |
|
1745 actionForNodeClass:AssignmentNode |
|
1746 put:[:node | |
|
1747 |val| |
|
1748 |
|
1749 node variable name = varName ifTrue:[ |
|
1750 "/ only look for wellknown types on the right side. |
|
1751 node expression isConstant ifTrue:[ |
|
1752 val := node expression evaluate. |
|
1753 val isArray ifTrue:[ |
|
1754 setOfTypes add:Array |
|
1755 ] ifFalse:[ |
|
1756 setOfTypes add:val class |
|
1757 ]. |
|
1758 ] ifFalse:[ |
|
1759 node expression isMessage ifTrue:[ |
|
1760 ( #(+ - * /) includes:node expression selector ) ifTrue:[ |
|
1761 setOfTypes add:Number |
|
1762 ] ifFalse:[ |
|
1763 ( #(// size) includes:node expression selector ) ifTrue:[ |
|
1764 setOfTypes add:Integer |
|
1765 ] ifFalse:[ |
|
1766 ( #(copy shallowCopy) includes:node expression selector ) ifTrue:[ |
|
1767 ] ifFalse:[ |
|
1768 ( #(new new: basicNew basicNew:) includes:node expression selector ) ifTrue:[ |
|
1769 node expression receiver isGlobal ifTrue:[ |
|
1770 setOfTypes add:node expression receiver evaluate |
|
1771 ]. |
|
1772 ] ifFalse:[ |
|
1773 self breakPoint:#cg. |
|
1774 ] |
|
1775 ] |
|
1776 ] |
|
1777 ] |
|
1778 ]. |
|
1779 ]. |
|
1780 ]. |
|
1781 true "/ yes - visit subnodes |
|
1782 ]. |
|
1783 visitor visit:tree. |
|
1784 ]. |
|
1785 ] |
|
1786 ] |
|
1787 ]. |
|
1788 ^ setOfTypes |
|
1789 ! |
|
1790 |
|
1791 classesOfNode:aNode |
|
1792 "returns the set of possible classes of a receiver. |
|
1793 or nil if unknown. |
|
1794 When showing possible completions for a message, |
|
1795 it is a good idea to know what the kind receiver is." |
|
1796 |
|
1797 | nm nodeVal receiverClass nodeSelector nodeReceiver mthd instVarClass| |
1710 |
1798 |
1711 aNode isBlock ifTrue:[ |
1799 aNode isBlock ifTrue:[ |
1712 ^ Block |
1800 ^ { Block } |
1713 ]. |
1801 ]. |
1714 |
|
1715 (nodeVal := self valueOfNode:aNode) notNil ifTrue:[ |
1802 (nodeVal := self valueOfNode:aNode) notNil ifTrue:[ |
1716 "/ knowing the value is always great!! |
1803 "/ knowing the value is always great!! |
1717 ^ nodeVal class |
1804 ^ { nodeVal class } |
1718 ]. |
1805 ]. |
1719 |
1806 |
1720 aNode isVariable ifTrue:[ |
1807 aNode isVariable ifTrue:[ |
1721 nm := aNode name. |
1808 nm := aNode name. |
1722 nm = 'self' ifTrue:[ |
1809 nm = 'self' ifTrue:[ |
1723 classOrNil isNil ifTrue:[^ UndefinedObject]. |
1810 classOrNil isNil ifTrue:[^ { UndefinedObject } ]. |
1724 ^ classOrNil |
1811 ^ { classOrNil } |
1725 ]. |
1812 ]. |
1726 nm = 'super' ifTrue:[ |
1813 nm = 'super' ifTrue:[ |
1727 classOrNil isNil ifTrue:[^ Object]. |
1814 classOrNil isNil ifTrue:[^ Object]. |
1728 ^ classOrNil superclass |
1815 ^ { classOrNil superclass } |
1729 ]. |
1816 ]. |
1730 nm = 'thisContext' ifTrue:[ |
1817 nm = 'thisContext' ifTrue:[ |
1731 ^ Context |
1818 ^ { Context } |
1732 ]. |
1819 ]. |
1733 |
1820 |
1734 "/ classOrNil notNil ifTrue:[ |
1821 classOrNil notNil ifTrue:[ |
|
1822 instVarClass := classOrNil whichClassDefinesInstVar:nm. |
|
1823 instVarClass notNil ifTrue:[ |
|
1824 ^ self classesOfInstVarNamed:nm inClass:instVarClass. |
|
1825 ]. |
1735 "/ (classOrNil allInstVarNames includes:nm) ifTrue:[ |
1826 "/ (classOrNil allInstVarNames includes:nm) ifTrue:[ |
1736 "/ "/ could look at existing instances here... |
1827 "/ "/ could look at existing instances here... |
1737 "/ self breakPoint:#cg. |
1828 "/ self breakPoint:#cg. |
1738 "/ ]. |
1829 "/ ]. |
1739 "/ ]. |
1830 ]. |
1740 ^ nil |
1831 ^ nil |
1741 ]. |
1832 ]. |
1742 |
1833 |
1743 aNode isMessage ifTrue:[ |
1834 aNode isMessage ifTrue:[ |
1744 nodeSelector := aNode selector. |
1835 nodeSelector := aNode selector. |
1746 |
1837 |
1747 "/ some hardwired knowlegde here |
1838 "/ some hardwired knowlegde here |
1748 receiverClass := self classOfNode:nodeReceiver. |
1839 receiverClass := self classOfNode:nodeReceiver. |
1749 receiverClass notNil ifTrue:[ |
1840 receiverClass notNil ifTrue:[ |
1750 nodeSelector == #class ifTrue:[ |
1841 nodeSelector == #class ifTrue:[ |
1751 ^ receiverClass class |
1842 ^ { receiverClass class } |
1752 ]. |
1843 ]. |
1753 |
1844 |
1754 receiverClass isBehavior ifTrue:[ |
1845 receiverClass isBehavior ifTrue:[ |
1755 mthd := receiverClass lookupMethodFor:nodeSelector. |
1846 mthd := receiverClass lookupMethodFor:nodeSelector. |
1756 receiverClass isMeta ifTrue:[ |
1847 receiverClass isMeta ifTrue:[ |
1757 ( #( #'new' #'basicNew' #'new:' #'basicNew:' #'with:' #'with:with:') includes: nodeSelector ) ifTrue:[ |
1848 ( #( #'new' #'basicNew' #'new:' #'basicNew:' #'with:' #'with:with:') includes: nodeSelector ) ifTrue:[ |
1758 ^ receiverClass theNonMetaclass |
1849 ^ { receiverClass theNonMetaclass } |
1759 ]. |
1850 ]. |
1760 "/ if that method sends one of new/basicNew/new:/basicNew:, assume it returns an instance of itself |
1851 "/ if that method sends one of new/basicNew/new:/basicNew:, assume it returns an instance of itself |
1761 mthd notNil ifTrue:[ |
1852 mthd notNil ifTrue:[ |
1762 ( mthd sendsAny:#( #'new' #'basicNew' #'new:' #'basicNew:' )) ifTrue:[ |
1853 ( mthd sendsAny:#( #'new' #'basicNew' #'new:' #'basicNew:' )) ifTrue:[ |
1763 ^ receiverClass theNonMetaclass |
1854 ^ { receiverClass theNonMetaclass } |
1764 ]. |
1855 ]. |
1765 ]. |
1856 ]. |
1766 ] ifFalse:[ |
1857 ] ifFalse:[ |
1767 mthd notNil ifTrue:[ |
1858 mthd notNil ifTrue:[ |
1768 (ParseTreeSearcher methodIsSetterMethod:mthd) ifTrue:[ |
1859 (ParseTreeSearcher methodIsSetterMethod:mthd) ifTrue:[ |
1769 ^ receiverClass. |
1860 ^ { receiverClass }. |
1770 ] |
1861 ] |
1771 ] |
1862 ] |
1772 ] |
1863 ] |
1773 ]. |
1864 ]. |
1774 ]. |
1865 ]. |
1775 classOrNil notNil ifTrue:[ |
1866 classOrNil notNil ifTrue:[ |
1776 (nodeReceiver isSelf and:[nodeSelector = #'class']) ifTrue:[ |
1867 (nodeReceiver isSelf and:[nodeSelector = #'class']) ifTrue:[ |
1777 ^ classOrNil class |
1868 ^ { classOrNil class } |
1778 ]. |
1869 ]. |
1779 ]. |
1870 ]. |
1780 |
1871 |
1781 (nodeSelector = #'asFilename') ifTrue:[ |
1872 (nodeSelector = #'asFilename') ifTrue:[ |
1782 ^ Filename |
1873 ^ { Filename } |
1783 ]. |
1874 ]. |
1784 (nodeSelector = #'asOrderedCollection') ifTrue:[ |
1875 (nodeSelector = #'asOrderedCollection') ifTrue:[ |
1785 ^ OrderedCollection |
1876 ^ { OrderedCollection } |
1786 ]. |
1877 ]. |
1787 (nodeSelector = #'asArray') ifTrue:[ |
1878 (nodeSelector = #'asArray') ifTrue:[ |
1788 ^ Array |
1879 ^ { Array } |
1789 ]. |
1880 ]. |
1790 (nodeSelector = #'asSet') ifTrue:[ |
1881 (nodeSelector = #'asSet') ifTrue:[ |
1791 ^ Set |
1882 ^ { Set } |
1792 ]. |
1883 ]. |
1793 (nodeSelector = #'size') ifTrue:[ |
1884 (nodeSelector = #'size') ifTrue:[ |
1794 ^ SmallInteger |
1885 ^ { SmallInteger } |
1795 ]. |
1886 ]. |
1796 |
1887 |
1797 "/ some wellknown boolean returners (need better type inference here) |
1888 "/ some wellknown boolean returners (need better type inference here) |
1798 (#( isNil notNil not isEmptyOrNil notEmptyOrNil notEmpty isEmpty |
1889 (#( isNil notNil not isEmptyOrNil notEmptyOrNil notEmpty isEmpty |
1799 isBehavior isMeta |
1890 isBehavior isMeta |
1800 = ~= == ~~ > >= < <= |
1891 = ~= == ~~ > >= < <= |
1801 includes: contains: |
1892 includes: contains: |
1802 and: or: |
1893 and: or: |
1803 exists atEnd |
1894 exists atEnd |
1804 ) includes:nodeSelector ) ifTrue:[ |
1895 ) includes:nodeSelector ) ifTrue:[ |
1805 ^ True "/ Boolean - not boolean; it does not contain the full protocol (would not find ifTrue:) |
1896 ^ { True } "/ Boolean - not boolean; it does not contain the full protocol (would not find ifTrue:) |
1806 ]. |
1897 ]. |
1807 |
1898 |
1808 ( #( + - * / // \\ ) includes:nodeSelector) ifTrue:[ |
1899 ( #( + - * / // \\ ) includes:nodeSelector) ifTrue:[ |
1809 "/ assume numeric |
1900 "/ assume numeric |
1810 ^ Number |
1901 ^ { Number } |
1811 ]. |
1902 ]. |
1812 |
1903 |
1813 ( #( class theMetaclass theNonMetaclass ) includes:nodeSelector) ifTrue:[ |
1904 ( #( class theMetaclass theNonMetaclass ) includes:nodeSelector) ifTrue:[ |
1814 "/ assume behavior |
1905 "/ assume behavior |
1815 ^ Behavior |
1906 ^ { Behavior } |
1816 ]. |
1907 ]. |
1817 ]. |
1908 ]. |
1818 ^ nil |
1909 ^ nil |
1819 |
|
1820 "Created: / 28-08-2013 / 16:34:53 / cg" |
|
1821 ! |
1910 ! |
1822 |
1911 |
1823 codeCompletionForLiteralSymbol:nodeOrNil element:tokenOrNil considerAll:considerAll into:actionBlock |
1912 codeCompletionForLiteralSymbol:nodeOrNil element:tokenOrNil considerAll:considerAll into:actionBlock |
1824 "looking for all symbols is way too much and inprecise; |
1913 "looking for all symbols is way too much and inprecise; |
1825 experiment: only present symbols which are used by the class, |
1914 experiment: only present symbols which are used by the class, |
1956 |
2045 |
1957 "/ Transcript show:'msg in '; show:methodOrNil; show:' / '; showCR:classOrNil. |
2046 "/ Transcript show:'msg in '; show:methodOrNil; show:' / '; showCR:classOrNil. |
1958 |
2047 |
1959 findBest := |
2048 findBest := |
1960 [:node :selector | |
2049 [:node :selector | |
1961 |srchClass srchClasses bestSelectors bestPrefixes |
2050 |srchClasses bestSelectors bestPrefixes |
1962 allMessagesSentToVariable classesImplementingAllMessages| |
2051 allMessagesSentToVariable classesImplementingAllMessages| |
1963 |
2052 |
1964 srchClass := self classOfNode:node. |
2053 srchClasses := self classesOfNode:node. |
1965 |
2054 |
1966 srchClass isNil ifTrue:[ |
2055 srchClasses isEmptyOrNil ifTrue:[ |
1967 node isVariable ifTrue:[ |
2056 node isVariable ifTrue:[ |
1968 allMessagesSentToVariable := Set new. |
2057 allMessagesSentToVariable := Set new. |
1969 rememberedNodes do:[:eachNode | |
2058 rememberedNodes do:[:eachNode | |
1970 eachNode allMessageNodesDo:[:eachMessage | |
2059 eachNode allMessageNodesDo:[:eachMessage | |
1971 |msgReceiver msgSelector| |
2060 |msgReceiver msgSelector| |
1989 srchClasses := classesImplementingAllMessages. |
2078 srchClasses := classesImplementingAllMessages. |
1990 ]. |
2079 ]. |
1991 ]. |
2080 ]. |
1992 ]. |
2081 ]. |
1993 bestSelectors := Set new. |
2082 bestSelectors := Set new. |
1994 srchClasses isEmptyOrNil ifTrue:[ srchClasses := Array with:srchClass ]. |
2083 srchClasses isEmptyOrNil ifTrue:[ |
1995 srchClasses do:[:srchClass | |
2084 bestSelectors addAll:( Parser findBest:50 selectorsFor:selector in:nil forCompletion:true ). |
1996 |bestForThisClass| |
2085 ] ifFalse:[ |
1997 |
2086 srchClasses do:[:srchClass | |
1998 bestForThisClass := Parser findBest:50 selectorsFor:selector in:srchClass forCompletion:true. |
2087 |bestForThisClass| |
1999 bestForThisClass := self |
2088 |
2000 withoutSelectorsUnlikelyFor:srchClass |
2089 bestForThisClass := Parser findBest:50 selectorsFor:selector in:srchClass forCompletion:true. |
2001 from:bestForThisClass |
2090 bestForThisClass := self |
2002 forPartial:selector. |
2091 withoutSelectorsUnlikelyFor:srchClass |
2003 bestSelectors addAll:bestForThisClass. |
2092 from:bestForThisClass |
|
2093 forPartial:selector. |
|
2094 bestSelectors addAll:bestForThisClass. |
|
2095 ]. |
2004 ]. |
2096 ]. |
2005 (bestSelectors includes:selector) ifTrue:[ |
2097 (bestSelectors includes:selector) ifTrue:[ |
2006 bestSelectors := bestSelectors select:[:sel | sel size > selector size]. |
2098 bestSelectors := bestSelectors select:[:sel | sel size > selector size]. |
2007 ]. |
2099 ]. |
2008 bestSelectors := bestSelectors asOrderedCollection. |
2100 bestSelectors := bestSelectors asOrderedCollection. |
3849 characterBeforeCursor := source at:(characterPositionOfCursor-1 max:1). "/ codeView characterBeforeCursor. |
3953 characterBeforeCursor := source at:(characterPositionOfCursor-1 max:1). "/ codeView characterBeforeCursor. |
3850 characterBeforeCursor isNil ifTrue:[ "at begin of line" ^ self]. |
3954 characterBeforeCursor isNil ifTrue:[ "at begin of line" ^ self]. |
3851 characterBeforeCursor == $. ifTrue:[ "at end of statement" ^ self]. |
3955 characterBeforeCursor == $. ifTrue:[ "at end of statement" ^ self]. |
3852 |
3956 |
3853 node isVariable ifTrue:[ |
3957 node isVariable ifTrue:[ |
|
3958 |classes cls| |
|
3959 |
3854 nodeIsInTemporaries := |
3960 nodeIsInTemporaries := |
3855 nodeParent notNil |
3961 nodeParent notNil |
3856 and:[ nodeParent isSequence |
3962 and:[ nodeParent isSequence |
3857 and:[ nodeParent temporaries notEmptyOrNil |
3963 and:[ nodeParent temporaries notEmptyOrNil |
3858 and:[ node stop <= nodeParent temporaries last stop ]]]. |
3964 and:[ node stop <= nodeParent temporaries last stop ]]]. |
|
3965 |
3859 nodeIsInTemporaries ifFalse:[ |
3966 nodeIsInTemporaries ifFalse:[ |
3860 "/ cursor must be right after the variable |
3967 "/ cursor must be right after the variable |
3861 characterPositionOfCursor >= (node stop) ifTrue:[ |
3968 codeView characterPositionOfCursor = (node stop + 1) ifTrue:[ |
3862 self codeCompletionForVariable:node into:actionBlock. |
3969 self codeCompletionForVariable:node into:actionBlock. |
|
3970 ^ self. |
3863 ] |
3971 ] |
3864 ]. |
3972 ]. |
3865 ^ self. |
3973 false ifTrue:[ |
|
3974 codeView characterPositionOfCursor = (node stop + 2) ifTrue:[ |
|
3975 "/ after a variable; |
|
3976 "/ offer local messages, if receiver type is known |
|
3977 classes := (self classesOfNode:node). |
|
3978 classes notEmptyOrNil ifTrue:[ |
|
3979 classes size > 1 ifTrue:[ |
|
3980 cls := classes anElement. |
|
3981 ] ifFalse:[ |
|
3982 cls := Behavior commonSuperclassOf:classes. |
|
3983 ] |
|
3984 ]. |
|
3985 cls notNil ifTrue:[ |
|
3986 |clsSelectors moreSelectors| |
|
3987 |
|
3988 "/ completion in a message-send |
|
3989 clsSelectors := cls methodDictionary keys. "/ Parser findBest:50 selectorsFor:'' in:cls forCompletion:true. |
|
3990 clsSelectors size < 30 ifTrue:[ |
|
3991 cls superclass notNil ifTrue:[ |
|
3992 moreSelectors := cls superclass methodDictionary keys. |
|
3993 clsSelectors size + moreSelectors size < 30 ifTrue:[ |
|
3994 clsSelectors := clsSelectors , moreSelectors. |
|
3995 ]. |
|
3996 ]. |
|
3997 ]. |
|
3998 "/ self codeCompletionForMessage:checkedNode into:actionBlock. |
|
3999 actionBlock value:clsSelectors value:nil value:nil. |
|
4000 ^ self. |
|
4001 ] |
|
4002 ] |
|
4003 ]. |
|
4004 ^ self |
3866 ]. |
4005 ]. |
3867 |
4006 |
3868 node isLiteral ifTrue:[ |
4007 node isLiteral ifTrue:[ |
3869 "/ however, user may want to complete a symbol inside a literal array!! |
4008 "/ however, user may want to complete a symbol inside a literal array!! |
3870 node value isArray ifTrue:[ |
4009 node value isArray ifTrue:[ |