blob: f82ff7f26df084969f19353729d564df58c30da6 [file] [log] [blame]
/*
* Copyright (c) 2012, the Dart project authors.
*
* Licensed under the Eclipse Public License v1.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.eclipse.org/legal/epl-v10.html
*
* 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.google.dart.engine.services.internal.refactoring;
import com.google.dart.engine.ast.AssignmentExpression;
import com.google.dart.engine.ast.AstNode;
import com.google.dart.engine.ast.ConstructorInitializer;
import com.google.dart.engine.ast.Expression;
import com.google.dart.engine.ast.ForStatement;
import com.google.dart.engine.ast.PrefixedIdentifier;
import com.google.dart.engine.ast.SimpleIdentifier;
import com.google.dart.engine.ast.TypeName;
import com.google.dart.engine.ast.VariableDeclaration;
import com.google.dart.engine.element.Element;
import com.google.dart.engine.element.FunctionElement;
import com.google.dart.engine.element.MethodElement;
import com.google.dart.engine.services.internal.correction.CorrectionUtils;
import com.google.dart.engine.services.internal.correction.StatementAnalyzer;
import com.google.dart.engine.services.status.RefactoringStatusContext;
import com.google.dart.engine.services.util.SelectionAnalyzer;
import com.google.dart.engine.utilities.source.SourceRange;
/**
* {@link SelectionAnalyzer} for "Extract Method" refactoring.
*/
public class ExtractMethodAnalyzer extends StatementAnalyzer {
public ExtractMethodAnalyzer(CorrectionUtils utils, SourceRange selection) {
super(utils, selection);
}
@Override
public Void visitAssignmentExpression(AssignmentExpression node) {
super.visitAssignmentExpression(node);
Expression lhs = node.getLeftHandSide();
if (isFirstSelectedNode(lhs)) {
invalidSelection(
"Cannot extract the left-hand side of an assignment.",
new RefactoringStatusContext(lhs));
}
return null;
}
@Override
public Void visitConstructorInitializer(ConstructorInitializer node) {
super.visitConstructorInitializer(node);
if (isFirstSelectedNode(node)) {
invalidSelection(
"Cannot extract a constructor initializer. Select expression part of initializer.",
new RefactoringStatusContext(node));
}
return null;
}
@Override
public Void visitForStatement(ForStatement node) {
super.visitForStatement(node);
if (node.getVariables() == getFirstSelectedNode()) {
invalidSelection("Cannot extract initialization part of a 'for' statement.");
} else if (node.getUpdaters().contains(getLastSelectedNode())) {
invalidSelection("Cannot extract increment part of a 'for' statement.");
}
return null;
}
@Override
public Void visitSimpleIdentifier(SimpleIdentifier node) {
super.visitSimpleIdentifier(node);
if (isFirstSelectedNode(node)) {
// name of declaration
if (node.inDeclarationContext()) {
invalidSelection("Cannot extract the name part of a declaration.");
}
// method name
Element element = node.getBestElement();
if (element instanceof FunctionElement || element instanceof MethodElement) {
invalidSelection("Cannot extract a single method name.");
}
// name in property access
if (node.getParent() instanceof PrefixedIdentifier
&& ((PrefixedIdentifier) node.getParent()).getIdentifier() == node) {
invalidSelection("Can not extract name part of a property access.");
}
}
return null;
}
@Override
public Void visitTypeName(TypeName node) {
super.visitTypeName(node);
if (isFirstSelectedNode(node)) {
invalidSelection("Cannot extract a single type reference.");
}
return null;
}
@Override
public Void visitVariableDeclaration(VariableDeclaration node) {
super.visitVariableDeclaration(node);
if (isFirstSelectedNode(node)) {
invalidSelection(
"Cannot extract a variable declaration fragment. Select whole declaration statement.",
new RefactoringStatusContext(node));
}
return null;
}
@Override
protected void handleNextSelectedNode(AstNode node) {
super.handleNextSelectedNode(node);
checkParent(node);
}
@Override
protected void handleSelectionEndsIn(AstNode node) {
super.handleSelectionEndsIn(node);
invalidSelection("The selection does not cover a set of statements or an expression. "
+ "Extend selection to a valid range.");
}
private void checkParent(AstNode node) {
AstNode firstParent = getFirstSelectedNode().getParent();
do {
node = node.getParent();
if (node == firstParent) {
return;
}
} while (node != null);
invalidSelection("Not all selected statements are enclosed by the same parent statement.");
}
private boolean isFirstSelectedNode(AstNode node) {
return getFirstSelectedNode() == node;
}
}