\See{hacking_undo_history}
\section{Wishful Thinking}
-
+\todoin{???}
\chapter{Composite Refactorings in Eclipse}
collects all the possible candidates for the refactoring. All the non-candidates
is found by an
\typewithref{no.uio.ifi.refaktor.analyze.collectors}{UnfixesCollector} that
-collects all the targets that will give some kind of error if used. The safe
-prefixes is found by subtracting from the set of candidate prefixes the prefixes
-that is enclosing any of the unfixes.\todo{Consolidate with section about
-``Computing safe prefixes''}
-
-\todoin{Continue here\ldots Clean up sections/subsections.}
+collects all the targets that will give some kind of error if used. All prefixes
+(and unfixes) are represented by a
+\typewithref{no.uio.ifi.refaktor.extractors}{Prefix}, and they are collected
+into sets of prefixes. The safe prefixes is found by subtracting from the set of
+candidate prefixes the prefixes that is enclosing any of the unfixes. A prefix
+is enclosing an unfix if the unfix is in the set of its sub-prefixes. As an
+example, \texttt{``a.b''} is enclosing \texttt{``a''}, as is \texttt{``a''}. The
+safe prefixes is unified in a \type{PrefixSet}. If a prefix has only one
+occurrence, and is a simple expression, it is considered unsuitable as a move
+target. This occurs in statements such as \texttt{``a.foo()''}. For such
+statements it bares no meaning to extract and move them. It only generates an
+extra method and the calling of it.
+
+\todoin{Clean up sections/subsections.}
\subsubsection{The \type{ExtractAndMoveMethodExecutor}}
If the analysis finds a possible target for the composite refactoring, it is
and
\typewithref{no.uio.ifi.refaktor.change.executors}{MoveMethodRefactoringExecutor}.
The \type{ExtractAndMoveMethodExecutor} is responsible for gluing the two
-together by feeding the \type{MoveMethodRefactoringExecutor} with the resources
-needed after executing the extract method refactoring.
+together by feeding the \type{MoveMethod\-RefactoringExecutor} with the
+resources needed after executing the extract method refactoring.
\See{postExtractExecution}
\subsubsection{The \type{ExtractMethodRefactoringExecutor}}
\subsection{Finding the IMethod}\label{postExtractExecution}
\todoin{Rename section. Write.}
-\subsection{The ExtractAndMoveMethodPrefixesExtractor Class}
-This extractor extracts properties needed for building the Extract and Move
-Method refactoring. It searches through the given selection to find safe
-prefixes, and those prefixes form a base that can be used to compute possible
-targets for the move part of the refactoring. It finds both the candidates, in
-the form of prefixes, and the non-candidates, called unfixes. All prefixes (and
-unfixes) are represented by a
-\typewithref{no.uio.ifi.refaktor.extractors}{Prefix}, and they are collected
-into prefix sets.\typeref{no.uio.ifi.refaktor.extractors.PrefixSet}.
-
+\subsection{Property collectors}
The prefixes and unfixes are found by property
collectors\typeref{no.uio.ifi.refaktor.extractors.collectors.PropertyCollector}.
A property collector follows the visitor pattern\citing{designPatterns} and is
\subsubsection{The PrefixesCollector}
The \typewithref{no.uio.ifi.refaktor.extractors.collectors}{PrefixesCollector}
-is of type \type{PropertyCollector}. It visits expression
+finds prefixes that makes up tha basis for calculating move targets for the
+Extract and Move Method refactoring. It visits expression
statements\typeref{org.eclipse.jdt.core.dom.ExpressionStatement} and creates
prefixes from its expressions in the case of method invocations. The prefixes
found is registered with a prefix set, together with all its sub-prefixes.
\todo{Rewrite in the case of changes to the way prefixes are found}
-\subsubsection{The UnfixesCollector}
+\subsubsection{The UnfixesCollector}\label{unfixes}
The \typewithref{no.uio.ifi.refaktor.extractors.collectors}{UnfixesCollector}
-finds unfixes within the selection. An unfix is a name that is assigned to
-within the selection. The reason that this cannot be allowed, is that the result
-would be an assignment to the \type{this} keyword, which is not valid in Java.
-
-\subsubsection{Computing Safe Prefixes}
-A safe prefix is a prefix that does not enclose an unfix. A prefix is enclosing
-an unfix if the unfix is in the set of its sub-prefixes. As an example,
-\texttt{``a.b''} is enclosing \texttt{``a''}, as is \texttt{``a''}. The safe
-prefixes is unified in a \type{PrefixSet} and can be fetched calling the
-\method{getSafePrefixes} method of the
-\type{ExtractAndMoveMethodPrefixesExtractor}.
+finds unfixes within a selection. That is prefixes that cannot be used as a
+basis for finding a move target in a refactoring.
+
+An unfix can be a name that is assigned to within a selection. The reason that
+this cannot be allowed, is that the result would be an assignment to the
+\type{this} keyword, which is not valid in Java \see{eclipse_bug_420726}.
+
+Prefixes that originates from variable declarations within the same selection
+are also considered unfixes. This is because when a method is moved, it needs to
+be called through a variable. If this variable is also within the method that is
+to be moved, this obviously cannot be done.
+
+Also considered as unfixes are variable references that are of types that is not
+suitable for moving a methods to. This can be either because it is not
+physically possible to move the method to the desired class or that it will
+cause compilation errors by doing so.
+
+If the type binding for a name is not resolved it is considered and unfix. The
+same applies to types that is only found in compiled code, so they have no
+underlying source that is accessible to us. (E.g. the \type{java.lang.String}
+class.)
+
+Interfaces types are not suitable as targets. This is simply because interfaces
+in java cannot contain methods with bodies. (This thesis does not deal with
+features of Java versions later than Java 7. Java 8 has interfaces with default
+implementations of methods.) Neither are local types allowed. This accounts for
+both local and anonymous classes. Anonymous classes are effectively the same as
+interface types with respect to unfixes. Local classes could in theory be used
+as targets, but this is not possible due to limitations of the implementation of
+the Extract and Move Method refactoring. The problem is that the refactoring is
+done in two steps, so the intermediate state between the two refactorings would
+not be legal Java code. In the case of local classes, the problem is that, in
+the intermediate step, a selection referencing a local class would need to take
+the local class as a parameter if it were to be extracted to a new method. This
+new method would need to live in the scope of the declaring class of the
+originating method. The local class would then not be in the scope of the
+extracted method, thus bringing the source code into an illegal state. One could
+imagine that the method was extracted and moved in one operation, without an
+intermediate state. Then it would make sense to include variables with types of
+local classes in the set of legal targets, since the local classes would then be
+in the scopes of the method calls. If this makes any difference for software
+metrics that measure coupling would be a different discussion.
+
+\begin{listing}
+\begin{multicols}{2}
+\begin{minted}[]{java}
+// Before
+void declaresLocalClass() {
+ class LocalClass {
+ void foo() {}
+ void bar() {}
+ }
+
+ LocalClass inst =
+ new LocalClass();
+ inst.foo();
+ inst.bar();
+}
+\end{minted}
+
+\columnbreak
+
+\begin{minted}[]{java}
+// After Extract Method
+void declaresLocalClass() {
+ class LocalClass {
+ void foo() {}
+ void bar() {}
+ }
+
+ LocalClass inst =
+ new LocalClass();
+ fooBar(inst);
+}
+
+// Intermediate step
+void fooBar(LocalClass inst) {
+ inst.foo();
+ inst.bar();
+}
+\end{minted}
+\end{multicols}
+\caption{When Extract and Move Method tries to use a variable with a local type
+as the move target, an intermediate step is taken that is not allowed. Here:
+\type{LocalClass} is not in the scope of \method{fooBar} in its intermediate
+location.}
+\label{lst:extractMethod_LocalClass}
+\end{listing}
+
+The last class of names that are considered unfixes is names used in null tests.
+These are tests that reads like this: if \texttt{<name>} equals \var{null} then
+do something. If allowing variables used in those kinds of expressions as
+targets for moving methods, we would end up with code containing boolean
+expressions like \texttt{this == null}, which would not be meaningful, since
+\var{this} would never be \var{null}.
\subsection{The Prefix Class}
-\todo{?}
+This class exists mainly for holding data about a prefix, such as the expression
+that the prefix represents and the occurrence count of the prefix within a
+selection. In addition to this, it has some functionality such as calculating
+its sub-prefixes and intersecting it with another prefix. The definition of the
+intersection between two prefixes is a prefix representing the longest common
+expression between the two.
+
\subsection{The PrefixSet Class}
+A prefix set holds elements of type \type{Prefix}. It is implemented with the
+help of a \typewithref{java.util}{HashMap} and contains some typical set
+operations, but it does not implement the \typewithref{java.util}{Set}
+interface, since the prefix set does not need all of the functionality a
+\type{Set} requires to be implemented. In addition It needs some other
+functionality not found in the \type{Set} interface. So due to the relatively
+limited use of prefix sets, and that it almost always needs to be referenced as
+such, and not a \type{Set<Prefix>}, it remains as an ad hoc solution to a
+concrete problem.
+
+There are two ways adding prefixes to a \type{PrefixSet}. The first is through
+its \method{add} method. This works like one would expect from a set. It adds
+the prefix to the set if it does not already contain the prefix. The other way
+is to \emph{register} the prefix with the set. When registering a prefix, if the
+set does not contain the prefix, it is just added. If the set contains the
+prefix, its count gets incremented. This is how the occurrence count is handled.
+
+The prefix set also computes the set of prefixes that is not enclosing any
+prefixes of another set. This is kind of a set difference operation only for
+enclosing prefixes.
\subsection{Hacking the Refactoring Undo
History}\label{hacking_undo_history}
-\todo{Where to put this section?}
+\todoin{Where to put this section?}
As an attempt to make multiple subsequent changes to the workspace appear as a
single action (i.e. make the undo changes appear as such), I tried to alter
local/anonymous classes. (The referenced variables need to be final and so
on\ldots)}
-\chapter{Eclipse Bugs}
+\chapter{Eclipse Bugs Found}
\todoin{Add other things and change headline?}
\section{Eclipse bug 420726: Code is broken when moving a method that is
-assigning to the parameter that is also the move destination}
+assigning to the parameter that is also the move
+destination}\label{eclipse_bug_420726}
This bug\footnote{\url{https://bugs.eclipse.org/bugs/show\_bug.cgi?id=420726}}
was found when analyzing what kinds of names that was to be considered as
-\emph{unfixes}.\todo{refer to unfixes}
+\emph{unfixes} \see{unfixes}.
\subsection{The bug}
The bug emerges when trying to move a method from one class to another, and when
class of the method to move is anonymous, the \var{this} expression in the
parameter list is not qualified with the declaring class' (empty) name.
+\section{Eclipse bug 429954: Extracting statement with reference to local type
+breaks code}\label{eclipse_bug_429954}
+The bug\footnote{\url{https://bugs.eclipse.org/bugs/show\_bug.cgi?id=429954}}
+was discovered when doing some changes to the way unfixes is computed.
+
+\subsection{The bug}
+The problem is that Eclipse is allowing selections that references variables of
+local types to be extracted. When this happens the code is broken, since the
+extracted method must take a parameter of a local type that is not in the
+methods scope. The problem is illustrated in
+\myref{lst:extractMethod_LocalClass}, but there in another setting.
+
+\subsection{Actions taken}
+There are no actions directly springing out of this bug, since the Extract
+Method refactoring cannot be meant to be this way. This is handled on the
+analysis stage of our Extract and Move Method refactoring. So names representing
+variables of local types is considered unfixes \see{unfixes}.
+\todoin{write more when fixing this in legal statements checker}
+
\chapter{Related Work}
\section{The compositional paradigm of refactoring}