View | Details | Raw Unified | Return to bug 332596 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/photran/internal/core/refactoring/AddSubroutineParameterRefactoring.java (+584 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 University of Illinois at Urbana-Champaign and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    UIUC - Initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.photran.internal.core.refactoring;
12
13
import java.util.ArrayList;
14
import java.util.Collection;
15
import java.util.Collections;
16
import java.util.HashSet;
17
import java.util.List;
18
import java.util.Set;
19
20
import org.eclipse.core.runtime.CoreException;
21
import org.eclipse.core.runtime.IProgressMonitor;
22
import org.eclipse.core.runtime.OperationCanceledException;
23
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
24
import org.eclipse.ltk.core.refactoring.RefactoringStatusContext;
25
import org.eclipse.photran.internal.core.analysis.binding.Definition;
26
import org.eclipse.photran.internal.core.analysis.binding.ScopingNode;
27
import org.eclipse.photran.internal.core.lexer.Terminal;
28
import org.eclipse.photran.internal.core.lexer.Token;
29
import org.eclipse.photran.internal.core.parser.ASTCallStmtNode;
30
import org.eclipse.photran.internal.core.parser.ASTEntityDeclNode;
31
import org.eclipse.photran.internal.core.parser.ASTIntConstNode;
32
import org.eclipse.photran.internal.core.parser.ASTListNode;
33
import org.eclipse.photran.internal.core.parser.ASTSeparatedListNode;
34
import org.eclipse.photran.internal.core.parser.ASTSubroutineArgNode;
35
import org.eclipse.photran.internal.core.parser.ASTSubroutineParNode;
36
import org.eclipse.photran.internal.core.parser.ASTSubroutineStmtNode;
37
import org.eclipse.photran.internal.core.parser.ASTSubroutineSubprogramNode;
38
import org.eclipse.photran.internal.core.parser.ASTTypeDeclarationStmtNode;
39
import org.eclipse.photran.internal.core.parser.IASTListNode;
40
import org.eclipse.photran.internal.core.parser.IASTNode;
41
import org.eclipse.photran.internal.core.parser.IBodyConstruct;
42
import org.eclipse.photran.internal.core.refactoring.infrastructure.FortranEditorRefactoring;
43
import org.eclipse.photran.internal.core.reindenter.Reindenter;
44
import org.eclipse.photran.internal.core.vpg.PhotranTokenRef;
45
import org.eclipse.photran.internal.core.vpg.PhotranVPG;
46
47
/**
48
 * 
49
 * 
50
 * This refactoring allows a user to select a subroutine and to add a new parameter to the list.
51
 * The refactoring will ask for a declaration line for the parameter, a default value with which to 
52
 * update all callers of the subroutine, and a position in the list at which to add the new parameter.
53
 * The refactoring ensures that the declaration line is valid, contains some logic to ensure that the 
54
 * default value matches the appropriate type, and ensures that the position is in bounds.  It then updates
55
 * the subroutine signature and updates the callers of the subroutine.  If the callers specify the variable name
56
 * in the call list, the refactoring will match this pattern.
57
 * 
58
 */
59
public class AddSubroutineParameterRefactoring extends FortranEditorRefactoring
60
{
61
    private ASTSubroutineStmtNode selectedSubroutine;
62
    private List<ASTSubroutineParNode> oldParameterList;
63
    private List<ASTSubroutineParNode> newParameterList;
64
    private int position = 0;
65
    private String parameterName = null;
66
    private String declaration = "integer, intent(in) :: newName"; //$NON-NLS-1$
67
    private String defaultValue = "0"; //$NON-NLS-1$
68
    private ASTTypeDeclarationStmtNode declStmt = null;
69
    private String type = "integer"; //$NON-NLS-1$
70
    
71
    public List<ASTSubroutineParNode> getOldParameterList() {
72
        return oldParameterList;
73
    }
74
  
75
    public String getDeclaration() {
76
        assert declaration != null;
77
        return this.declaration;
78
    }
79
    
80
    public int getPosition() {
81
        return this.position;
82
    }
83
    
84
    public String getDefault() {
85
        assert defaultValue != null;
86
        return this.defaultValue;
87
    }
88
    
89
    public void setPosition(int position) {
90
        this.position = position;
91
    }
92
    
93
    /*
94
     * Sets the declaration member, but first checks that an appropriate type is at the
95
     * beggining of the declaration.  If not, it assumes that "real" should be prepended.
96
     * The type member is then set to this type.
97
     * 
98
     * @param declaration The declaration to be set.
99
     */
100
    public void setDeclaration(String declaration) {
101
        // Add "real" to all declaration lines that do not specify a type to avoid parser errors.
102
        
103
        String[] declArgs = declaration.split(","); //$NON-NLS-1$
104
        String[] validTypes = {"integer","real","logical","double","character"};  //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
105
        boolean hasTypeDefined = false;
106
        for (int i = 0; i < validTypes.length; i++) {
107
            if (validTypes[i].equals(declArgs[0])) {
108
                hasTypeDefined = true;
109
                type = declArgs[0];
110
                break;
111
            }
112
        }
113
        
114
        if (!hasTypeDefined) {
115
            type = "real"; //$NON-NLS-1$
116
            if (declArgs.length == 1)
117
                declaration = "real, " + declaration; //$NON-NLS-1$
118
            else declaration = "real" + " :: " + declaration; //$NON-NLS-1$ //$NON-NLS-2$
119
        }
120
        
121
        this.declaration = declaration;
122
    }
123
    
124
    public void setDefaultValue(String defValue) {
125
        defaultValue = defValue;
126
    }
127
    
128
    /* (non-Javadoc)
129
     * @see org.eclipse.rephraserengine.core.vpg.refactoring.VPGRefactoring#doCheckInitialConditions(org.eclipse.ltk.core.refactoring.RefactoringStatus, org.eclipse.core.runtime.IProgressMonitor)
130
     */
131
    @Override
132
    protected void doCheckInitialConditions(RefactoringStatus status, IProgressMonitor pm)
133
        throws org.eclipse.rephraserengine.core.vpg.refactoring.VPGRefactoring.PreconditionFailure
134
    {
135
        ensureProjectHasRefactoringEnabled(status);
136
137
        ensureSubroutineIsSelected();
138
139
        if(!matchingDeclarationsInInterfacesUniquelyBind())
140
            status.addWarning(Messages.AddSubroutineParameterRefactoring_matchingDeclarationsDoNotUniquelyBind);
141
        
142
        oldParameterList = getSubroutineParameters();
143
    }
144
145
    /*
146
     * By looking at the AST tree, starting at the node supplied to the refactoring as the selected node, this method
147
     * determines if a subroutine node has been selected or not.
148
     * 
149
     */
150
    private void ensureSubroutineIsSelected()
151
        throws org.eclipse.rephraserengine.core.vpg.refactoring.VPGRefactoring.PreconditionFailure
152
    {
153
        IASTNode temporaryNode = findEnclosingNode(astOfFileInEditor, selectedRegionInEditor);
154
155
        if(temporaryNode == null)
156
            fail(Messages.AddSubroutineParameterRefactoring_selectSubroutineError);
157
158
        if(temporaryNode instanceof ASTSubroutineSubprogramNode)
159
            selectedSubroutine = ((ASTSubroutineSubprogramNode)temporaryNode).getSubroutineStmt();
160
        else if(temporaryNode instanceof ASTSubroutineStmtNode)
161
        {
162
            if(temporaryNode.findNearestAncestor(ASTSubroutineSubprogramNode.class) == null)
163
                fail(Messages.AddSubroutineParameterRefactoring_selectSubroutineError);
164
            selectedSubroutine = (ASTSubroutineStmtNode)temporaryNode;
165
        }
166
        else
167
            fail(Messages.AddSubroutineParameterRefactoring_selectSubroutineError);
168
    }
169
    
170
    /*
171
     * This method determines if a matching declaration already exists in scope, and if so, will fail the refactoring.
172
     * 
173
     */
174
    private boolean matchingDeclarationsInInterfacesUniquelyBind()
175
    {
176
        for(Definition declaration : getInterfaceDeclarations())
177
            if(declaration.resolveInterfaceBinding().size() != 1)
178
                return false;
179
        
180
        return true;
181
    }
182
183
    /* (non-Javadoc)
184
     * @see org.eclipse.rephraserengine.core.vpg.refactoring.VPGRefactoring#doCheckFinalConditions(org.eclipse.ltk.core.refactoring.RefactoringStatus, org.eclipse.core.runtime.IProgressMonitor)
185
     */
186
    @Override
187
    protected void doCheckFinalConditions(RefactoringStatus status, IProgressMonitor pm)
188
        throws org.eclipse.rephraserengine.core.vpg.refactoring.VPGRefactoring.PreconditionFailure
189
    {
190
        ensureDeclarationIsValid();
191
        
192
        parameterName = declStmt.getEntityDeclList().get(0).getObjectName().getObjectName().getText();
193
        
194
        ensurePositionIsValid();
195
        
196
        ensureDefaultValueIsValid();
197
198
        checkForConflictingBindings(pm, status);
199
    }
200
201
    /*
202
     * This method ensures that the default value supplied is valid by applying logic that 
203
     * tests whether or not the default type supplied matches the type supplied in the declaration line.
204
     * For example, .true. and .false. are reserved for logical types.  This method also ensures that the
205
     * default value is not a variable name beginning with a number.
206
     * 
207
     */
208
    private void ensureDefaultValueIsValid()
209
        throws org.eclipse.rephraserengine.core.vpg.refactoring.VPGRefactoring.PreconditionFailure
210
    {
211
        if (defaultValue == null || 
212
            defaultValue.equals("") ||  //$NON-NLS-1$
213
            isWhiteSpace(defaultValue) || 
214
            isVariableNameBeginningWithNumber(defaultValue) || 
215
            (isTrueOrFalse(defaultValue) && !type.equals("logical")) ||  //$NON-NLS-1$
216
            (isANumber(defaultValue) && (!type.equals("integer") && !type.equals("real"))) ||   //$NON-NLS-1$//$NON-NLS-2$
217
            (isRealAndNotInteger(defaultValue) && type.equals("integer")) ||  //$NON-NLS-1$
218
            (defaultValue.equals("null") && !declaration.contains("pointer")))  //$NON-NLS-1$ //$NON-NLS-2$
219
            fail(Messages.AddSubroutineParameterRefactoring_InvalidDefaultValue);
220
    }
221
222
    /*
223
     * @param str A string to be tested
224
     * @return <code> true </code> if the selected string is a real number, and <code> false </code> if the selected string
225
     * is ann integer or not a number.
226
     * 
227
     */
228
    private boolean isRealAndNotInteger(String str) {
229
        if (isANumber(str)) {
230
            try {
231
                Integer.parseInt(str);
232
            }
233
            catch (NumberFormatException e) {
234
                return true;
235
            }
236
        }
237
        return false;
238
    }
239
240
    /*
241
     * @param str A string to be tested
242
     * @return <code> true </code> if the selected string is ".true." or ".false.", and <code> false </code> if the selected string
243
     * is anything else.
244
     */
245
    private boolean isTrueOrFalse(String str) {
246
    	if (str == null)
247
    		return false;
248
        return str.equals(".true.") || str.equals(".false."); //$NON-NLS-1$ //$NON-NLS-2$
249
    }
250
251
    /*
252
     * @param str A string to be tested
253
     * @return <code> true </code> if the string begins with a number but is not a number (hence, a variable name beginning with a number)
254
     * and <code> false </code> otherwise.
255
     * 
256
     */
257
    private boolean isVariableNameBeginningWithNumber(String str) {
258
        if (str != null) {
259
            if (str.length() != 0) {
260
                if (isANumber(str.substring(0,1))) {
261
                    if (!isANumber(str))
262
                        return true;
263
                }
264
            }
265
        }
266
267
        return false;
268
    }
269
270
    /*
271
     * @param str A string
272
     * @return <code> true </code> if str is a number.
273
     */
274
    private boolean isANumber(String str) {
275
        try {
276
            Double.parseDouble(str);
277
        }
278
        catch (NumberFormatException e) {
279
            return false;
280
        }
281
        return true;
282
    }
283
284
    /*
285
     * This function ensures that the position given to the refactoring is in bounds for the current size of the list, and if not,
286
     * fails the refactoring.
287
     * 
288
     */
289
    private void ensurePositionIsValid()
290
        throws org.eclipse.rephraserengine.core.vpg.refactoring.VPGRefactoring.PreconditionFailure {
291
        if (position > oldParameterList.size() || position < 0)
292
            fail(Messages.AddSubroutineParameterRefactoring_InvalidParameterPosition);
293
    }
294
295
    /*
296
     * This function attempts to produce a declaration node by passing the declaration line on to a parser.  If this node is returned
297
     * as an error node, the refactoring fails.
298
     * 
299
     */
300
    private void ensureDeclarationIsValid()
301
        throws org.eclipse.rephraserengine.core.vpg.refactoring.VPGRefactoring.PreconditionFailure {
302
        IBodyConstruct decl = parseLiteralStatementNoFail(declaration);
303
        if (decl == null || !(decl instanceof ASTTypeDeclarationStmtNode))
304
            fail(Messages.AddSubroutineParameterRefactoring_InvalidDeclaration);
305
        declStmt = (ASTTypeDeclarationStmtNode)decl;
306
        IASTListNode<ASTEntityDeclNode> entityDeclList = declStmt.getEntityDeclList();
307
        if (entityDeclList == null) {
308
            fail(Messages.AddSubroutineParameterRefactoring_InvalidDeclaration);
309
        }
310
    }
311
312
    /*
313
     * This function checks to see whether or not the variable name supplied to the refactoring is already in scope in the subroutine.
314
     * 
315
     */
316
    private void checkForConflictingBindings(IProgressMonitor pm, RefactoringStatus status) {
317
        Definition def = arbitraryDefinitionInScope();
318
        if (def == null) return; // No declarations in scope, so the new one can't conflict
319
320
        checkForConflictingBindings(pm,
321
            new ConflictingBindingErrorHandler(status),
322
            def,
323
            Collections.<PhotranTokenRef>emptyList(),
324
            parameterName);
325
    }
326
    
327
    /*
328
     * This function returns an arbitrary definition line in scope of the current node.  It is used to iterate through
329
     * the declarations to see if there are any conflicts.
330
     * 
331
     */
332
    private Definition arbitraryDefinitionInScope() {
333
        ScopingNode enclosingScope = selectedSubroutine.findNearestAncestor(ScopingNode.class);
334
        List<Definition> allDefs = enclosingScope.getAllDefinitions();
335
        if (allDefs.isEmpty())
336
            return null;
337
        else
338
            return allDefs.get(0);
339
    }
340
   
341
    /*
342
     * @param str A string
343
     * @return <code> true </code> if str is only white space.  This is used to test if default values are nothing but white space.
344
     */
345
    private boolean isWhiteSpace(String str)
346
    {
347
        return str.replace(" ", "").replace("\t", "").equals(""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
348
    }
349
    
350
    /* (non-Javadoc)
351
     * @see org.eclipse.rephraserengine.core.vpg.refactoring.VPGRefactoring#doCreateChange(org.eclipse.core.runtime.IProgressMonitor)
352
     */
353
    @Override
354
    protected void doCreateChange(IProgressMonitor pm) throws CoreException,
355
        OperationCanceledException
356
    {
357
358
        buildNewParameterListWithNewParameter();
359
        
360
        // Change the arguments list to the new list
361
        permuteArgumentList(selectedSubroutine);
362
        
363
        addArgumentDeclaration(selectedSubroutine);
364
        
365
        permuteCallSites();
366
367
        addChangeFromModifiedAST(fileInEditor, pm);
368
        vpg.releaseAST(fileInEditor);
369
        
370
    }
371
    
372
    /*
373
     * This function adds the declaration line to the subroutine.
374
     */
375
    private void addArgumentDeclaration(ASTSubroutineStmtNode subroutineStatement)
376
    {
377
        ASTSubroutineSubprogramNode subroutine = (ASTSubroutineSubprogramNode)subroutineStatement.getParent();
378
        
379
        IASTListNode<IBodyConstruct> statements = subroutine.getBody();
380
        if (statements == null) {
381
            statements = new ASTListNode<IBodyConstruct>();
382
            subroutine.setBody(statements);
383
        }
384
        
385
        statements.add(0, declStmt);
386
        Reindenter.reindent(declStmt, astOfFileInEditor);
387
        
388
    }
389
390
    /* (non-Javadoc)
391
     * @see org.eclipse.ltk.core.refactoring.Refactoring#getName()
392
     */
393
    @Override
394
    public String getName()
395
    {
396
        return Messages.AddSubroutineParameterRefactoring_Name;
397
    }
398
    
399
    /*
400
     * This function returns the list of subroutine parameters from the selected subroutine node.
401
     */
402
    public List<ASTSubroutineParNode> getSubroutineParameters()
403
    {
404
        if(selectedSubroutine.getSubroutinePars() != null)
405
            return selectedSubroutine.getSubroutinePars();
406
407
        return new ArrayList<ASTSubroutineParNode>();
408
    }
409
    
410
    /*
411
     * This function returns a collection of interface declarations.
412
     */
413
    private Collection<Definition> getInterfaceDeclarations()
414
    {
415
        List<Definition> subroutineDefinitions = selectedSubroutine.getSubroutineName().getSubroutineName().resolveBinding();
416
        
417
        if(subroutineDefinitions.size() != 1)
418
            return new ArrayList<Definition>();
419
        
420
        return subroutineDefinitions.get(0).findMatchingDeclarationsInInterfaces();
421
    }
422
    
423
    /*
424
     * This function builds the new parameter list to be supplied to the subroutine node by adding the new parameter to
425
     * the list in the appropriate position.
426
     */
427
    public void buildNewParameterListWithNewParameter()
428
    {
429
        // Create new variable
430
        ASTSubroutineParNode newParameter = new ASTSubroutineParNode();
431
        Token variableName = generateVariableName();
432
        newParameter.setVariableName(variableName);
433
        
434
        // Create new list
435
        newParameterList = new ArrayList<ASTSubroutineParNode>(oldParameterList);
436
        newParameterList.add(position, newParameter);
437
        
438
    }
439
440
    /*
441
     * This function returns a token for a variable with the name of the new parameter name.
442
     */
443
    private Token generateVariableName()
444
    {
445
        Token variableName = new Token(Terminal.T_IDENT, parameterName);
446
        return variableName;
447
    }
448
449
    /*
450
     * This function changes the argument list of the subroutine statement node to the new list generated in buildNewParameterListWithNewParameter()
451
     */
452
    protected void permuteArgumentList(ASTSubroutineStmtNode node)
453
    {
454
        ASTSeparatedListNode<ASTSubroutineParNode> newParameterList = new ASTSeparatedListNode<ASTSubroutineParNode>(new Token(Terminal.T_COMMA, ","), this.newParameterList); //$NON-NLS-1$
455
        node.setSubroutinePars(newParameterList);
456
    }
457
    
458
    /*
459
     * This function changes all call sites to be updated to have the new argument in place, and will match any calling pattern currently used.
460
     */
461
    private void permuteCallSites()
462
    {
463
        for(ASTCallStmtNode callStmt : getCallSites())
464
        {
465
            int previousArgumentListSize = 0;
466
467
            if(callStmt.getArgList() != null) {
468
                previousArgumentListSize = callStmt.getArgList().size();
469
            }
470
471
            // Generate new IExpression Node for the default value
472
            ASTIntConstNode expr = new ASTIntConstNode();
473
            expr.setIntConst(new Token(Terminal.T_ICON, defaultValue));
474
            ASTSubroutineArgNode addedParArg = new ASTSubroutineArgNode();
475
            addedParArg.setExpr(expr);
476
            
477
            // Test to see if the call site is using the "(variableName = value, variablename = value)" pattern, or simply the "(value, value)" pattern
478
            // The new parameter should follow this pattern at the call site, and should assume the (value) pattern if the list was previously empty.
479
            if (previousArgumentListSize > 0) {
480
                int positionToCompareTo = Math.min(position, previousArgumentListSize-1);
481
                ASTSubroutineParNode firstParameter = oldParameterList.get(positionToCompareTo);
482
                ASTSubroutineArgNode firstParameterArgument = getActualArgFromCallStmt(callStmt, firstParameter.getVariableName(), positionToCompareTo);
483
                if (firstParameterArgument.getName() != null)
484
                    addedParArg.setName(new Token(Terminal.T_IDENT, parameterName));
485
            }
486
            
487
            ArrayList<ASTSubroutineArgNode> newParameterListForCallSite = new ArrayList<ASTSubroutineArgNode>(); 
488
            
489
            for (int i = 0; i < previousArgumentListSize; i++) {
490
                ASTSubroutineParNode desiredPar = oldParameterList.get(i);
491
                ASTSubroutineArgNode desiredParArgument = getActualArgFromCallStmt(callStmt, desiredPar.getVariableName(), i);
492
                newParameterListForCallSite.add(desiredParArgument);
493
            }
494
495
            newParameterListForCallSite.add(position, addedParArg);
496
497
            
498
            ASTSeparatedListNode<ASTSubroutineArgNode> newArgList = new ASTSeparatedListNode<ASTSubroutineArgNode>(new Token(Terminal.T_COMMA, ","), newParameterListForCallSite); //$NON-NLS-1$
499
            callStmt.setArgList(newArgList);
500
        }
501
    }
502
    
503
    /*
504
     * This function returns the set of call sites for the subroutine that was selected.
505
     */
506
    private Set<ASTCallStmtNode> getCallSites()
507
    {
508
        List<Definition> subroutineDefinitions = selectedSubroutine.getSubroutineName().getSubroutineName().resolveBinding();
509
        HashSet<ASTCallStmtNode> result = new HashSet<ASTCallStmtNode>();
510
511
        if (subroutineDefinitions.size() != 1)
512
            return result; 
513
514
        for(PhotranTokenRef tokenRef : subroutineDefinitions.get(0).findAllReferences(true))
515
        {
516
            Token token = tokenRef.findToken();
517
518
            ASTCallStmtNode callStmtNode = token.findNearestAncestor(ASTCallStmtNode.class);
519
520
            if(callStmtNode != null)
521
                result.add(callStmtNode);
522
        }
523
524
        return result;
525
    }
526
    
527
    /*
528
     * This function gets an argument from a call statement, in order to check if it follows the pattern of "Variablename = Value".
529
     */
530
    private ASTSubroutineArgNode getActualArgFromCallStmt(ASTCallStmtNode callStmt, Token desiredParName, int desiredParIndex)
531
    {
532
        for(int i = 0; i < callStmt.getArgList().size(); i++)
533
        {
534
            ASTSubroutineArgNode argument = callStmt.getArgList().get(i);
535
            if(argument.getName() == null || desiredParName == null)
536
            {
537
                if(i == desiredParIndex)
538
                    return argument;
539
            }
540
            else
541
            {
542
                String argumentName = PhotranVPG.canonicalizeIdentifier(argument.getName().getText());
543
                String parameterName = PhotranVPG.canonicalizeIdentifier(desiredParName.getText());
544
                if(argumentName.equals(parameterName))
545
                    return argument;
546
            }
547
        }
548
        return null;
549
    }
550
551
    /*
552
     * This class handles all error cases for conflicting variable names or bindings.
553
     */
554
    private final class ConflictingBindingErrorHandler implements IConflictingBindingCallback
555
    {
556
        private final RefactoringStatus status;
557
558
        private ConflictingBindingErrorHandler(RefactoringStatus status) { this.status = status; }
559
560
        public void addConflictError(List<Conflict> conflictingDef)
561
        {
562
            Conflict conflict = conflictingDef.get(0);
563
564
            String msg = Messages.bind(Messages.AddSubroutineParameterRefactoring_NameConflictsWith, conflict.name, vpg.getDefinitionFor(conflict.tokenRef));
565
            RefactoringStatusContext context = createContext(conflict.tokenRef); // Highlights problematic definition
566
            status.addError(msg, context);
567
        }
568
569
        public void addConflictWarning(List<Conflict> conflictingDef)
570
        {
571
            Conflict conflict = conflictingDef.get(0);
572
573
            String msg = Messages.bind(Messages.AddSubroutineParameterRefactoring_NameMightConflictWithSubprogram, conflict.name);
574
            RefactoringStatusContext context = createContext(conflict.tokenRef); // Highlights problematic definition
575
            status.addWarning(msg, context);
576
        }
577
578
        public void addReferenceWillChangeError(String newName, Token reference)
579
        {
580
            throw new IllegalStateException();
581
        }
582
    }
583
 
584
}
(-)src/org/eclipse/photran/internal/core/refactoring/Messages.java (+16 lines)
Lines 64-69 Link Here
64
    public static String AddOnlyToUseStmtRefactoring_ProjectDoesNotExist;
64
    public static String AddOnlyToUseStmtRefactoring_ProjectDoesNotExist;
65
65
66
    public static String AddOnlyToUseStmtRefactoring_SelectModuleName;
66
    public static String AddOnlyToUseStmtRefactoring_SelectModuleName;
67
    
68
    public static String AddSubroutineParameterRefactoring_InvalidDeclaration;
69
    
70
    public static String AddSubroutineParameterRefactoring_InvalidDefaultValue;
71
    
72
    public static String AddSubroutineParameterRefactoring_InvalidParameterPosition;
73
    
74
    public static String AddSubroutineParameterRefactoring_matchingDeclarationsDoNotUniquelyBind;
75
    
76
    public static String AddSubroutineParameterRefactoring_Name;
77
    
78
    public static String AddSubroutineParameterRefactoring_NameConflictsWith;
79
    
80
    public static String AddSubroutineParameterRefactoring_NameMightConflictWithSubprogram;
81
82
    public static String AddSubroutineParameterRefactoring_selectSubroutineError;
67
83
68
    public static String EncapsulateVariableRefactoring_CannotEncapsulateArrays;
84
    public static String EncapsulateVariableRefactoring_CannotEncapsulateArrays;
69
85
(-)src/org/eclipse/photran/internal/core/refactoring/messages.properties (+8 lines)
Lines 21-26 Link Here
21
AddOnlyToUseStmtRefactoring_PleaseSelectModuleName=Please select a module name.
21
AddOnlyToUseStmtRefactoring_PleaseSelectModuleName=Please select a module name.
22
AddOnlyToUseStmtRefactoring_ProjectDoesNotExist=Project does not exist\!
22
AddOnlyToUseStmtRefactoring_ProjectDoesNotExist=Project does not exist\!
23
AddOnlyToUseStmtRefactoring_SelectModuleName=Please select the name of the module in the USE statement.
23
AddOnlyToUseStmtRefactoring_SelectModuleName=Please select the name of the module in the USE statement.
24
AddSubroutineParameterRefactoring_InvalidDeclaration=Invalid declaration line for new parameter.
25
AddSubroutineParameterRefactoring_InvalidDefaultValue=Invalid default value for this parameter for all callers of this subroutine.
26
AddSubroutineParameterRefactoring_InvalidParameterPosition=Parameter position is out of bounds.
27
AddSubroutineParameterRefactoring_matchingDeclarationsDoNotUniquelyBind=Matching declarations in interface blocks do not uniquely bind to the selected subroutine.
28
AddSubroutineParameterRefactoring_Name=Add Subroutine Parameter
29
AddSubroutineParameterRefactoring_NameConflictsWith=The name "{0}" conflicts with {1}
30
AddSubroutineParameterRefactoring_NameMightConflictWithSubprogram=Name might have conflict with subprogram.
31
AddSubroutineParameterRefactoring_selectSubroutineError=Please select a subroutine definition.
24
PermuteSubroutineArgsRefactoring_matchingDeclarationsDoNotUniquelyBind=Matching declarations in interface blocks do not uniquely bind to the selected subroutine.
32
PermuteSubroutineArgsRefactoring_matchingDeclarationsDoNotUniquelyBind=Matching declarations in interface blocks do not uniquely bind to the selected subroutine.
25
PermuteSubroutineArgsRefactoring_name=Permute Subroutine Arguments
33
PermuteSubroutineArgsRefactoring_name=Permute Subroutine Arguments
26
PermuteSubroutineArgsRefactoring_selectedTextNotSubroutine=The selected text is not a subroutine.  Please select a subroutine.
34
PermuteSubroutineArgsRefactoring_selectedTextNotSubroutine=The selected text is not a subroutine.  Please select a subroutine.
(-)refactoring-test-code/add-subroutine-parameter/test1-basic/add_subroutine_parameter_1.f90 (+6 lines)
Added Link Here
1
program basic ! basic test, adding an integer with intent in, default value 0, at position 0.
2
3
end program basic
4
subroutine sub(z) !<<<<< 4, 1, 4, 5, integer; intent(in) :: y, 0, 0, pass
5
    integer, intent(in) :: z
6
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test1-basic/add_subroutine_parameter_1.f90.result (+7 lines)
Added Link Here
1
program basic ! basic test, adding an integer with intent in, default value 0, at position 0.
2
3
end program basic
4
subroutine sub(y,z) !<<<<< 4, 1, 4, 5, integer; intent(in) :: y, 0, 0, pass
5
    integer, intent(in) :: y
6
    integer, intent(in) :: z
7
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test10-fail-invalidtype/add_subroutine_parameter_10.f90 (+6 lines)
Added Link Here
1
program invalidtype ! Fails because the type specified is invalid in the declaration line.
2
3
end program invalidtype
4
subroutine sub(z) !<<<<< 4, 1, 4, 5, invalidtype :: y, 0, 0, fail-final
5
    integer, intent(in) :: z
6
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test11-updatecallsitewhenvariablenamesaddedincall/add_subroutine_parameter_11.f90 (+7 lines)
Added Link Here
1
program variablenameaddedincallsite ! Tests that when y is added, the call site adds y=0
2
    implicit none
3
    call sub(z=2)
4
end program variablenameaddedincallsite
5
subroutine sub(z) !<<<<< 5, 1, 5, 5, integer; intent(in) :: y, 1, 0, pass
6
    integer, intent(in) :: z
7
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test11-updatecallsitewhenvariablenamesaddedincall/add_subroutine_parameter_11.f90.result (+8 lines)
Added Link Here
1
program variablenameaddedincallsite ! Tests that when y is added, the call site adds y=0
2
    implicit none
3
    call sub(z=2,y=0)
4
end program variablenameaddedincallsite
5
subroutine sub(z,y) !<<<<< 5, 1, 5, 5, integer; intent(in) :: y, 1, 0, pass
6
    integer, intent(in) :: y
7
    integer, intent(in) :: z
8
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test12-includevalidattributes/add_subroutine_parameter_12.f90 (+6 lines)
Added Link Here
1
program validattributes ! Tests that valid attributes (intent(inout)) are allowed.
2
3
end program validattributes
4
subroutine sub(z) !<<<<< 4, 1, 4, 5, integer; intent(inout) :: y, 0, 0, pass
5
    integer, intent(in) :: z
6
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test12-includevalidattributes/add_subroutine_parameter_12.f90.result (+7 lines)
Added Link Here
1
program validattributes ! Tests that valid attributes (intent(inout)) are allowed.
2
3
end program validattributes
4
subroutine sub(y,z) !<<<<< 4, 1, 4, 5, integer; intent(inout) :: y, 0, 0, pass
5
    integer, intent(inout) :: y
6
    integer, intent(in) :: z
7
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test13-fail-invalidattribute/add_subroutine_parameter_13.f90 (+6 lines)
Added Link Here
1
program invalidvalidattributes ! Tests that invalid attributes fail
2
3
end program invalidvalidattributes
4
subroutine sub(z) !<<<<< 4, 1, 4, 5, integer; intent(inoot) :: y, 0, 0, fail-final
5
    integer, intent(in) :: z
6
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test14-fail-conflictingattributes/add_subroutine_parameter_14.f90 (+6 lines)
Added Link Here
1
program conflictingattributes ! Tests that conflicting attributes (two types) fail.
2
3
end program conflictingattributes
4
subroutine sub(z) !<<<<< 4, 1, 4, 5, integer; real; intent(out) :: y, 0, 0, fail-final
5
    integer, intent(in) :: z
6
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test15-fail-conflictingvariablenames/add_subroutine_parameter_15.f90 (+7 lines)
Added Link Here
1
program conflictingvariablenames ! Tests that a parameter cannot be given the same name as another in scope.
2
3
end program conflictingvariablenames
4
subroutine sub(z) !<<<<< 4, 1, 4, 5, integer; intent(in) :: alreadyused, 0, 0, fail-final
5
	real :: alreadyused
6
    integer, intent(in) :: z
7
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test16-fail-whitespacevariablename/add_subroutine_parameter_16.f90 (+6 lines)
Added Link Here
1
program whitespacevariablename ! Tests that a variable name cannot be set to just white space.
2
3
end program whitespacevariablename
4
subroutine sub(z) !<<<<< 4, 1, 4, 5, integer; intent(inout) ::  	, 0, 0, fail-final
5
    integer, intent(in) :: z
6
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test17-fail-parameternamebeginswithnumber/add_subroutine_parameter_17.f90 (+6 lines)
Added Link Here
1
program parameternamebeginswithnumber ! Tests that the variable name cannot begin with a number
2
3
end program parameternamebeginswithnumber
4
subroutine sub(z) !<<<<< 4, 1, 4, 5, integer :: 1y, 0, 0, fail-final
5
    integer, intent(in) :: z
6
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test18-fail-defaultvalueisvariablestartingwithnumber/add_subroutine_parameter_18.f90 (+6 lines)
Added Link Here
1
program defaultvalueisvariablestartingwithnumber ! Tests that the default value cannot be set to an invalid variable name
2
3
end program defaultvalueisvariablestartingwithnumber
4
subroutine sub(z) !<<<<< 4, 1, 4, 5, integer :: y, 0, 1defval, fail-final
5
    integer, intent(in) :: z
6
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test19-fail-defaultvalueisrealwhentypeisinteger/add_subroutine_parameter_19.f90 (+6 lines)
Added Link Here
1
program defaultvalueisrealforinteger ! Tests that an integer cannot be given a real default value.
2
3
end program defaultvalueisrealforinteger
4
subroutine sub(z) !<<<<< 4, 1, 4, 5, integer :: y, 0, 1.7, fail-final
5
    integer, intent(in) :: z
6
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test2-updatecallsite/add_subroutine_parameter_2.f90 (+7 lines)
Added Link Here
1
program updatecallsite ! Tests that the call site is updated appropriately - basic.
2
    implicit none
3
    call sub(2)
4
end program updatecallsite
5
subroutine sub(z) !<<<<< 5, 1, 5, 5, integer; intent(in) :: y, 0, 0, pass
6
    integer, intent(in) :: z
7
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test2-updatecallsite/add_subroutine_parameter_2.f90.result (+8 lines)
Added Link Here
1
program updatecallsite ! Tests that the call site is updated appropriately - basic.
2
    implicit none
3
    call sub(0,2)
4
end program updatecallsite
5
subroutine sub(y,z) !<<<<< 5, 1, 5, 5, integer; intent(in) :: y, 0, 0, pass
6
    integer, intent(in) :: y
7
    integer, intent(in) :: z
8
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test20-fail-defaultvalueisnumberwhentypeisnonnumber/add_subroutine_parameter_20.f90 (+6 lines)
Added Link Here
1
program defaultvalueisnumberfornonnumbertype ! Tests that non number types cannot be given a number as a default value.
2
3
end program defaultvalueisnumberfornonnumbertype
4
subroutine sub(z) !<<<<< 4, 1, 4, 5, logical :: y, 0, 1, fail-final
5
    integer, intent(in) :: z
6
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test21-fail-defaultvalueisnullwhentypeisnotpointer/add_subroutine_parameter_21.f90 (+6 lines)
Added Link Here
1
program defaultvalueisnullfornonpointer ! Tests that null cannot be the default value for a non pointer
2
3
end program defaultvalueisnullfornonpointer
4
subroutine sub(z) !<<<<< 4, 1, 4, 5, integer :: y, 0, null, fail-final
5
    integer, intent(in) :: z
6
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test22-basicpointer/add_subroutine_parameter_22.f90 (+6 lines)
Added Link Here
1
program basicpointer ! Tests that pointers can be passed as a parameter.
2
3
end program basicpointer
4
subroutine sub(z) !<<<<< 4, 1, 4, 5, integer; intent(in); pointer :: y, 0, null, pass
5
    integer, intent(in) :: z
6
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test22-basicpointer/add_subroutine_parameter_22.f90.result (+7 lines)
Added Link Here
1
program basicpointer ! Tests that pointers can be passed as a parameter.
2
3
end program basicpointer
4
subroutine sub(y,z) !<<<<< 4, 1, 4, 5, integer; intent(in); pointer :: y, 0, null, pass
5
    integer, intent(in), pointer :: y
6
    integer, intent(in) :: z
7
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test3-updatecallsitewithorder/add_subroutine_parameter_3.f90 (+7 lines)
Added Link Here
1
program updatecallsitewithorder ! Tests that the position of the parameter is correctly set.
2
    implicit none
3
    call sub(2)
4
end program updatecallsitewithorder
5
subroutine sub(z) !<<<<< 5, 1, 5, 5, integer; intent(in) :: y, 1, 0, pass
6
    integer, intent(in) :: z
7
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test3-updatecallsitewithorder/add_subroutine_parameter_3.f90.result (+8 lines)
Added Link Here
1
program updatecallsitewithorder ! Tests that the position of the parameter is correctly set.
2
    implicit none
3
    call sub(2,0)
4
end program updatecallsitewithorder
5
subroutine sub(z,y) !<<<<< 5, 1, 5, 5, integer; intent(in) :: y, 1, 0, pass
6
    integer, intent(in) :: y
7
    integer, intent(in) :: z
8
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test4-fail-negativeposition/add_subroutine_parameter_4.f90 (+6 lines)
Added Link Here
1
program negativeposition ! Tests that the refactoring fails with negative positions requested.
2
3
end program negativeposition
4
subroutine sub(z) !<<<<< 4, 1, 4, 5, integer; intent(in) :: y, -1, 0, fail-final
5
    integer, intent(in) :: z
6
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test5-fail-outofboundsposition/add_subroutine_parameter_5.f90 (+6 lines)
Added Link Here
1
program outofbounds ! Tests that the refactoring fails for requests to place the new parameter in a position that is out of bounds.
2
3
end program outofbounds
4
subroutine sub(z) !<<<<< 4, 1, 4, 5, integer; intent(in) :: y, 3, 0, fail-final
5
    integer, intent(in) :: z
6
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test6-fail-whitespacedefaultvalue/add_subroutine_parameter_6.f90 (+6 lines)
Added Link Here
1
program whitespacedefaultvalue ! Tests that the refactoring does not allow the default value to be white space
2
3
end program whitespacedefaultvalue
4
subroutine sub(z) !<<<<< 4, 1, 4, 5, integer; intent(in) :: y, 0,    	, fail-final
5
    integer, intent(in) :: z
6
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test7-basicarray/add_subroutine_parameter_7.f90 (+6 lines)
Added Link Here
1
program basicarray ! Tests that arrays can be passed.
2
3
end program basicarray
4
subroutine sub(z) !<<<<< 4, 1, 4, 5, integer; intent(in); dimension(2) :: y, 0, (/ 2; 3 /), pass
5
    integer, intent(in) :: z
6
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test7-basicarray/add_subroutine_parameter_7.f90.result (+7 lines)
Added Link Here
1
program basicarray ! Tests that arrays can be passed.
2
3
end program basicarray
4
subroutine sub(y,z) !<<<<< 4, 1, 4, 5, integer; intent(in); dimension(2) :: y, 0, (/ 2; 3 /), pass
5
    integer, intent(in), dimension(2) :: y
6
    integer, intent(in) :: z
7
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test8-logicalbasic/add_subroutine_parameter_8.f90 (+6 lines)
Added Link Here
1
program logicalbasic ! Tests that logical parameters work correctly.
2
3
end program logicalbasic
4
subroutine sub(z) !<<<<< 4, 1, 4, 5, logical; intent(in) :: y, 0, .true., pass
5
    integer, intent(in) :: z
6
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test8-logicalbasic/add_subroutine_parameter_8.f90.result (+7 lines)
Added Link Here
1
program logicalbasic ! Tests that logical parameters work correctly.
2
3
end program logicalbasic
4
subroutine sub(y,z) !<<<<< 4, 1, 4, 5, logical; intent(in) :: y, 0, .true., pass
5
    logical, intent(in) :: y
6
    integer, intent(in) :: z
7
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test9-dontsetvariabletype/add_subroutine_parameter_9.f90 (+6 lines)
Added Link Here
1
program dontsetvariabletype ! Tests that the default variable type is set to real
2
3
end program dontsetvariabletype
4
subroutine sub(z) !<<<<< 4, 1, 4, 5, intent(in) :: y, 0, 3, pass
5
    integer, intent(in) :: z
6
end subroutine
(-)refactoring-test-code/add-subroutine-parameter/test9-dontsetvariabletype/add_subroutine_parameter_9.f90.result (+7 lines)
Added Link Here
1
program dontsetvariabletype ! Tests that the default variable type is set to real
2
3
end program dontsetvariabletype
4
subroutine sub(y,z) !<<<<< 4, 1, 4, 5, intent(in) :: y, 0, 3, pass
5
    real, intent(in) :: y
6
    integer, intent(in) :: z
7
end subroutine
(-)src/org/eclipse/photran/internal/tests/refactoring/AddSubroutineParameterTestSuite.java (+57 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 University of Illinois at Urbana-Champaign and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    UIUC - Initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.photran.internal.tests.refactoring;
12
13
import junit.framework.Test;
14
15
import org.eclipse.core.resources.IFile;
16
import org.eclipse.jface.text.TextSelection;
17
import org.eclipse.photran.internal.core.refactoring.AddSubroutineParameterRefactoring;
18
import org.eclipse.photran.internal.tests.Activator;
19
import org.eclipse.photran.internal.tests.PhotranRefactoringTestSuiteFromMarkers;
20
21
/**
22
 * 
23
 * @author Marc Celani, Joe Handzik, Joe Gonzalez, Jason Patel
24
 */
25
public class AddSubroutineParameterTestSuite extends
26
    PhotranRefactoringTestSuiteFromMarkers<AddSubroutineParameterRefactoring>
27
{
28
    private static final String DIR = "refactoring-test-code/add-subroutine-parameter";
29
30
    public static Test suite() throws Exception
31
    {
32
        return new AddSubroutineParameterTestSuite();
33
    }
34
35
    public AddSubroutineParameterTestSuite() throws Exception
36
    {
37
        super(Activator.getDefault(),
38
              "Running Add Subroutine Parameter refactoring in",
39
              DIR,
40
              AddSubroutineParameterRefactoring.class);
41
    }
42
43
    @Override
44
    protected boolean configureRefactoring(AddSubroutineParameterRefactoring refactoring,
45
                                           IFile file,
46
                                           TextSelection selection,
47
                                           String[] markerText)
48
    {
49
        boolean shouldSucceed = super.configureRefactoring(refactoring, file, selection, markerText);
50
        refactoring.setDeclaration(markerText[4].replaceAll(";", ","));
51
        refactoring.setPosition(Integer.parseInt(markerText[5]));
52
        if (!markerText[6].equals("_dont_call"))
53
            refactoring.setDefaultValue(markerText[6]);
54
55
        return shouldSucceed;
56
    }
57
}
(-)OSGI-INF/l10n/bundle.properties (-2 / +2 lines)
Lines 3-21 Link Here
3
command.name = Rename...
3
command.name = Rename...
4
command.name.0 = Extract Procedure...
4
command.name.0 = Extract Procedure...
5
command.name.1 = Extract Local Variable...
5
command.name.1 = Extract Local Variable...
6
command.name.21 = Add Subroutine Parameter...
6
actionSet.description = Fortran Refactorings
7
actionSet.description = Fortran Refactorings
7
actionSet.label = Fortran Refactorings
8
actionSet.label = Fortran Refactorings
8
action.label = Re&name...
9
action.label = Re&name...
9
action.label.0 = E&xtract Procedure...
10
action.label.0 = E&xtract Procedure...
10
action.label.1 = Extract &Local Variable...
11
action.label.1 = Extract &Local Variable...
12
action.label.21 = Add Subrouti&ne Parameter...
11
page.name = Analysis/Refactoring
13
page.name = Analysis/Refactoring
12
category.description = Navigation
14
category.description = Navigation
13
category.name.0 = Navigation
15
category.name.0 = Navigation
14
command.description = Open Declaration
16
command.description = Open Declaration
15
command.name.2 = Open Declaration
16
actionSet.description.0 = Fortran Analysis Actions
17
actionSet.description.0 = Fortran Analysis Actions
17
actionSet.label.0 = Fortran Analysis Actions
18
actionSet.label.0 = Fortran Analysis Actions
18
action.label.2 = &Open Declaration
19
action.label.3 = &Open Declaration
19
action.label.3 = &Open Declaration
20
extension.name = Fortran Search
20
extension.name = Fortran Search
21
page.label = Fortran Search
21
page.label = Fortran Search
(-)plugin.xml (-1 / +18 lines)
Lines 20-25 Link Here
20
      <group><!-- Extract XYZ -->
20
      <group><!-- Extract XYZ -->
21
         <editorRefactoring command="org.eclipse.photran.ui.ExtractProcedureRefactoringCommand" />
21
         <editorRefactoring command="org.eclipse.photran.ui.ExtractProcedureRefactoringCommand" />
22
         <editorRefactoring command="org.eclipse.photran.ui.ExtractLocalVariableRefactoringCommand" />
22
         <editorRefactoring command="org.eclipse.photran.ui.ExtractLocalVariableRefactoringCommand" />
23
        <editorRefactoring command="org.eclipse.photran.ui.AddSubroutineParameterRefactoringCommand" />
23
      </group>
24
      </group>
24
      <group><!-- Refactorings that change local variable declarations -->
25
      <group><!-- Refactorings that change local variable declarations -->
25
         <resourceRefactoring
26
         <resourceRefactoring
Lines 151-156 Link Here
151
            categoryId="org.eclipse.photran.ui.RefactoringCategory"
152
            categoryId="org.eclipse.photran.ui.RefactoringCategory"
152
            id="org.eclipse.photran.ui.ExtractLocalVariableRefactoringCommand">
153
            id="org.eclipse.photran.ui.ExtractLocalVariableRefactoringCommand">
153
      </command>
154
      </command>
155
      <command
156
            name="%command.name.21"
157
            categoryId="org.eclipse.photran.ui.RefactoringCategory"
158
            id="org.eclipse.photran.ui.AddSubroutineParameterRefactoringCommand">
159
      </command>
154
   </extension>
160
   </extension>
155
161
156
   <!-- 2. Optionally associate the command with an accelerator key -->
162
   <!-- 2. Optionally associate the command with an accelerator key -->
Lines 174-179 Link Here
174
            contextId="org.eclipse.photran.ui.FortranEditorContext"
180
            contextId="org.eclipse.photran.ui.FortranEditorContext"
175
            commandId="org.eclipse.photran.ui.ExtractLocalVariableRefactoringCommand"
181
            commandId="org.eclipse.photran.ui.ExtractLocalVariableRefactoringCommand"
176
     />
182
     />
183
        <key
184
            sequence="M3+M2+T"
185
            schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
186
            contextId="org.eclipse.photran.ui.FortranEditorContext"
187
            commandId="org.eclipse.photran.ui.AddSubroutineParameterRefactoringCommand"
188
     />
177
   </extension>
189
   </extension>
178
190
179
   <!-- 3. Add the command to Photran's Refactoring action set -->
191
   <!-- 3. Add the command to Photran's Refactoring action set -->
Lines 199-204 Link Here
199
               definitionId="org.eclipse.photran.ui.ExtractLocalVariableRefactoringCommand"
211
               definitionId="org.eclipse.photran.ui.ExtractLocalVariableRefactoringCommand"
200
               class="org.eclipse.photran.internal.ui.refactoring.ExtractLocalVariableAction"
212
               class="org.eclipse.photran.internal.ui.refactoring.ExtractLocalVariableAction"
201
               id="org.eclipse.photran.ui.ExtractLocalVariableRefactoringAction"/>
213
               id="org.eclipse.photran.ui.ExtractLocalVariableRefactoringAction"/>
214
         <action
215
               label="%action.label.21"
216
               definitionId="org.eclipse.photran.ui.AddSubroutineParameterRefactoringCommand"
217
               class="org.eclipse.photran.internal.ui.refactoring.AddSubroutineParameterAction"
218
               id="org.eclipse.photran.ui.AddSubroutineParameterRefactoringAction"/>
202
      </actionSet>
219
      </actionSet>
203
   </extension>
220
   </extension>
204
221
Lines 353-359 Link Here
353
            id="org.eclipse.photran.ui.Reindenter">
370
            id="org.eclipse.photran.ui.Reindenter">
354
	     <action 
371
	     <action 
355
	           label="%action.label.reindent.0" 
372
	           label="%action.label.reindent.0" 
356
               menubarPath="org.eclipse.photran.ui.source.menu/indentationActions"
373
               menubarPath="edit/additions"
357
               definitionId="org.eclipse.photran.ui.ReindenterCommand"
374
               definitionId="org.eclipse.photran.ui.ReindenterCommand"
358
	           class="org.eclipse.photran.internal.ui.actions.ReindentAction"
375
	           class="org.eclipse.photran.internal.ui.actions.ReindentAction"
359
	           id="org.eclipse.photran.ui.ReindenterAction">
376
	           id="org.eclipse.photran.ui.ReindenterAction">
(-)src/org/eclipse/photran/internal/ui/refactoring/AddSubroutineParameterAction.java (+170 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007, 2009 University of Illinois at Urbana-Champaign and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     UIUC - Initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.photran.internal.ui.refactoring;
12
13
import java.util.List;
14
15
import org.eclipse.core.resources.IFile;
16
import org.eclipse.ltk.ui.refactoring.UserInputWizardPage;
17
import org.eclipse.photran.core.IFortranAST;
18
import org.eclipse.photran.internal.core.lexer.Token;
19
import org.eclipse.photran.internal.core.parser.ASTSubroutineParNode;
20
import org.eclipse.photran.internal.core.refactoring.AddSubroutineParameterRefactoring;
21
import org.eclipse.photran.internal.core.vpg.PhotranVPG;
22
import org.eclipse.rephraserengine.core.vpg.refactoring.VPGRefactoring;
23
import org.eclipse.swt.SWT;
24
import org.eclipse.swt.events.ModifyEvent;
25
import org.eclipse.swt.events.ModifyListener;
26
import org.eclipse.swt.layout.GridData;
27
import org.eclipse.swt.layout.GridLayout;
28
import org.eclipse.swt.widgets.Composite;
29
import org.eclipse.swt.widgets.Label;
30
import org.eclipse.swt.widgets.Table;
31
import org.eclipse.swt.widgets.TableColumn;
32
import org.eclipse.swt.widgets.TableItem;
33
import org.eclipse.swt.widgets.Text;
34
import org.eclipse.ui.IEditorActionDelegate;
35
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
36
37
/**
38
 * Handles the Add Subroutine Parameter action in the Fortran editor's Refactoring popup menu and in
39
 * the Refactor menu in the workbench menu bar.
40
 * 
41
 * @author Joe Handzik, Joe Gonzales, Marc Celani, Jason Patel
42
 */
43
public class AddSubroutineParameterAction extends AbstractFortranRefactoringActionDelegate
44
    implements IWorkbenchWindowActionDelegate, IEditorActionDelegate
45
{
46
    public AddSubroutineParameterAction()
47
    {
48
        super(AddSubroutineParameterRefactoring.class,
49
            FortranAddSubroutineParameterRefactoringWizard.class);
50
    }
51
52
    @Override
53
    protected VPGRefactoring<IFortranAST, Token, PhotranVPG> getRefactoring(List<IFile> files)
54
    {
55
        AddSubroutineParameterRefactoring r = new AddSubroutineParameterRefactoring();
56
        r.initialize(getFortranEditor().getIFile(), getFortranEditor().getSelection());
57
        return r;
58
    }
59
60
    public static class FortranAddSubroutineParameterRefactoringWizard extends
61
        AbstractFortranRefactoringWizard
62
    {
63
        protected AddSubroutineParameterRefactoring addSubRefactoring;
64
65
        public FortranAddSubroutineParameterRefactoringWizard(AddSubroutineParameterRefactoring r)
66
        {
67
            super(r);
68
            this.addSubRefactoring = r;
69
        }
70
71
        @Override
72
        protected void doAddUserInputPages()
73
        {
74
            addPage(new UserInputWizardPage(addSubRefactoring.getName())
75
            {
76
                protected Text declField;
77
                protected Text locationField;
78
                protected Text defaultField;
79
80
                public void createControl(Composite parent)
81
                {
82
                    Composite group = new Composite(parent, SWT.NONE);
83
                    initializeDialogUnits(group);
84
                    setControl(group);
85
                    group.setLayout(new GridLayout(3, false));
86
87
                    GridData threeCol = new GridData();
88
                    threeCol.horizontalSpan = 3;
89
90
                    Label lbl = new Label(group, SWT.NONE);
91
                    lbl.setText(Messages.AddSubroutineParameterAction_DeclarationLabel);
92
                    Label lbl3 = new Label(group, SWT.NONE);
93
                    lbl3.setText(Messages.AddSubroutineParameterAction_DefaultLabel);
94
                    Label lbl2 = new Label(group, SWT.NONE);
95
                    lbl2.setText(Messages.AddSubroutineParameterAction_LocationLabel);
96
97
                    declField = new Text(group, SWT.BORDER);
98
                    declField.setText(addSubRefactoring.getDeclaration());
99
                    declField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
100
                    declField.selectAll();
101
                    declField.addModifyListener(new ModifyListener()
102
                    {
103
                        public void modifyText(ModifyEvent e)
104
                        {
105
                            addSubRefactoring.setDeclaration(declField.getText());
106
                        }
107
                    });
108
109
                    defaultField = new Text(group, SWT.BORDER);
110
                    defaultField.setText(addSubRefactoring.getDefault());
111
                    defaultField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
112
                    defaultField.selectAll();
113
                    defaultField.addModifyListener(new ModifyListener()
114
                    {
115
                        public void modifyText(ModifyEvent e)
116
                        {
117
                            addSubRefactoring.setDefaultValue(defaultField.getText());
118
                        }
119
                    });
120
121
                    locationField = new Text(group, SWT.BORDER);
122
                    locationField.setText(String.valueOf(addSubRefactoring.getPosition()));
123
                    locationField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
124
                    locationField.selectAll();
125
                    locationField.addModifyListener(new ModifyListener()
126
                    {
127
                        public void modifyText(ModifyEvent e)
128
                        {
129
                            addSubRefactoring.setPosition(Integer.parseInt(locationField.getText()));
130
                        }
131
                    });
132
133
                    //creates the table that lists the variables that exist in the subroutine
134
                    List<ASTSubroutineParNode> parList = addSubRefactoring.getOldParameterList();
135
136
                    GridData gridData = new GridData(GridData.VERTICAL_ALIGN_END);
137
                    gridData.horizontalSpan = 3;
138
                    gridData.horizontalAlignment = GridData.FILL;
139
                    
140
                    Table table = new Table (group, SWT.BORDER );
141
                    table.setLinesVisible (true);
142
                    table.setHeaderVisible (true);
143
                    table.setLayoutData(gridData);
144
                    for (int i = 0; i < parList.size(); i++){
145
                        TableColumn column = new TableColumn (table, SWT.NONE);
146
                        column.setText (String.valueOf(i));
147
                    }   
148
                    TableItem item = new TableItem (table, SWT.NONE);
149
                    for (int i = 0; i < parList.size(); i++){               
150
                        item.setText (i, parList.get(i).getVariableName().getText());
151
                    }
152
                    for (int i=0; i<parList.size(); i++) {
153
                        table.getColumn (i).pack ();
154
                    }   
155
156
                    // Call once for sure, just in case the user doesn't modify the text
157
                    // addSubRefactoring.setDeclaration(declField.getText());
158
159
                    int offset = declField.getText().indexOf(":: "); //$NON-NLS-1$
160
                    if (offset < 0)
161
                        offset = 0;
162
                    else
163
                        offset = offset + ":: ".length(); //$NON-NLS-1$
164
                    declField.setSelection(offset, declField.getText().length());
165
                    declField.setFocus();
166
                }
167
            });
168
        }
169
    }
170
}
(-)src/org/eclipse/photran/internal/ui/refactoring/Messages.java (+8 lines)
Lines 19-24 Link Here
19
{
19
{
20
    private static final String BUNDLE_NAME = "org.eclipse.photran.internal.ui.refactoring.messages"; //$NON-NLS-1$
20
    private static final String BUNDLE_NAME = "org.eclipse.photran.internal.ui.refactoring.messages"; //$NON-NLS-1$
21
21
22
    public static String AddSubroutineParameterAction_DefaultLabel;
23
24
    public static String AddSubroutineParameterAction_DeclarationLabel;
25
22
    public static String AbstractFortranRefactoringActionDelegate_ErrorTitle;
26
    public static String AbstractFortranRefactoringActionDelegate_ErrorTitle;
23
27
24
    public static String AbstractFortranRefactoringActionDelegate_FileInEditorCannotBeRefactored;
28
    public static String AbstractFortranRefactoringActionDelegate_FileInEditorCannotBeRefactored;
Lines 62-67 Link Here
62
    public static String CommonVarNamesInputPage_OriginalNameLabel;
66
    public static String CommonVarNamesInputPage_OriginalNameLabel;
63
67
64
    public static String ExtractLocalVariableAction_DeclarationLabel;
68
    public static String ExtractLocalVariableAction_DeclarationLabel;
69
    
70
    //public static String AddSubroutineParameterAction_DeclarationLabel;
65
71
66
    public static String ExtractProcedureAction_SubroutineNameLabel;
72
    public static String ExtractProcedureAction_SubroutineNameLabel;
67
73
Lines 84-89 Link Here
84
    public static String RenameAction_MatchExternalSubprograms;
90
    public static String RenameAction_MatchExternalSubprograms;
85
91
86
    public static String RenameAction_RenameAtoB;
92
    public static String RenameAction_RenameAtoB;
93
94
    public static String AddSubroutineParameterAction_LocationLabel;
87
    static
95
    static
88
    {
96
    {
89
        // initialize resource bundle
97
        // initialize resource bundle
(-)src/org/eclipse/photran/internal/ui/refactoring/messages.properties (+3 lines)
Lines 2-7 Link Here
2
AbstractFortranRefactoringActionDelegate_FileInEditorCannotBeRefactored=The file in the editor cannot be refactored.\n\nFortran files can only be refactored if they are located inside a Fortran project in your workspace.
2
AbstractFortranRefactoringActionDelegate_FileInEditorCannotBeRefactored=The file in the editor cannot be refactored.\n\nFortran files can only be refactored if they are located inside a Fortran project in your workspace.
3
AddOnlyToUseStmtInputPage_ClickOKMessage=Click OK to add the ONLY clause to the selected USE statement. To see what changes will be made, click Preview.
3
AddOnlyToUseStmtInputPage_ClickOKMessage=Click OK to add the ONLY clause to the selected USE statement. To see what changes will be made, click Preview.
4
AddOnlyToUseStmtInputPage_SelectModuleEntitiesLabel=Select the module entities to add to the ONLY clause.
4
AddOnlyToUseStmtInputPage_SelectModuleEntitiesLabel=Select the module entities to add to the ONLY clause.
5
AddSubroutineParameterAction_DeclarationLabel=Declaration:
6
AddSubroutineParameterAction_LocationLabel=Position:
7
AddSubroutineParameterAction_DefaultLabel=Default Value:
5
PermuteSubroutineArgsInputPage_alternateReturnColumnLabel=Alternate Return
8
PermuteSubroutineArgsInputPage_alternateReturnColumnLabel=Alternate Return
6
PermuteSubroutineArgsInputPage_alternateReturnErrorLabel=The relative order of alternate returns must remain the same.\n
9
PermuteSubroutineArgsInputPage_alternateReturnErrorLabel=The relative order of alternate returns must remain the same.\n
7
PermuteSubroutineArgsInputPage_downButtonLabel=Down
10
PermuteSubroutineArgsInputPage_downButtonLabel=Down

Return to bug 332596