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 (+653 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 Joe Handzik, Joe Gonzales, Marc Celani, and Jason Patel.
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
 *    Joe Handzik, Joe Gonzales, Marc Celani, and Jason Patel - 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. The
51
 * 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
53
 * parameter. The refactoring ensures that the declaration line is valid, contains some logic to
54
 * ensure that the default value matches the appropriate type, and ensures that the position is in
55
 * bounds. It then updates the subroutine signature and updates the callers of the subroutine. If
56
 * the callers specify the variable name in the call list, the refactoring will match this pattern.
57
 * 
58
 * @author Joe Handzik, Joe Gonzales, Marc Celani, Jason Patel
59
 */
60
public class AddSubroutineParameterRefactoring extends FortranEditorRefactoring
61
{
62
    private ASTSubroutineStmtNode selectedSubroutine;
63
64
    private List<ASTSubroutineParNode> oldParameterList;
65
66
    private List<ASTSubroutineParNode> newParameterList;
67
68
    private int position = 0;
69
70
    private String parameterName = null;
71
72
    private String declaration = "integer, intent(in) :: newName"; //$NON-NLS-1$
73
74
    private String defaultValue = "0"; //$NON-NLS-1$
75
76
    private ASTTypeDeclarationStmtNode declStmt = null;
77
78
    private String type = "integer"; //$NON-NLS-1$
79
80
    public List<ASTSubroutineParNode> getOldParameterList()
81
    {
82
        return oldParameterList;
83
    }
84
85
    public String getDeclaration()
86
    {
87
        assert declaration != null;
88
        return this.declaration;
89
    }
90
91
    public int getPosition()
92
    {
93
        return this.position;
94
    }
95
96
    public String getDefault()
97
    {
98
        assert defaultValue != null;
99
        return this.defaultValue;
100
    }
101
102
    public void setPosition(int position)
103
    {
104
        this.position = position;
105
    }
106
107
    /*
108
     * Sets the declaration member, but first checks that an appropriate type is at the beggining of
109
     * the declaration. If not, it assumes that "real" should be prepended. The type member is then
110
     * set to this type.
111
     * 
112
     * @param declaration The declaration to be set.
113
     */
114
    public void setDeclaration(String declaration)
115
    {
116
        // Add "real" to all declaration lines that do not specify a type to avoid parser errors.
117
118
        String[] declArgs = declaration.split(","); //$NON-NLS-1$
119
        String[] validTypes = { "integer", "real", "logical", "double", "character" }; //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
120
        boolean hasTypeDefined = false;
121
        for (int i = 0; i < validTypes.length; i++)
122
        {
123
            if (validTypes[i].equals(declArgs[0]))
124
            {
125
                hasTypeDefined = true;
126
                type = declArgs[0];
127
                break;
128
            }
129
        }
130
131
        if (!hasTypeDefined)
132
        {
133
            type = "real"; //$NON-NLS-1$
134
            if (declArgs.length == 1)
135
                declaration = "real, " + declaration; //$NON-NLS-1$
136
            else
137
                declaration = "real" + " :: " + declaration; //$NON-NLS-1$ //$NON-NLS-2$
138
        }
139
140
        this.declaration = declaration;
141
    }
142
143
    public void setDefaultValue(String defValue)
144
    {
145
        defaultValue = defValue;
146
    }
147
148
    /*
149
     * (non-Javadoc)
150
     * 
151
     * @see
152
     * org.eclipse.rephraserengine.core.vpg.refactoring.VPGRefactoring#doCheckInitialConditions(
153
     * org.eclipse.ltk.core.refactoring.RefactoringStatus,
154
     * org.eclipse.core.runtime.IProgressMonitor)
155
     */
156
    @Override
157
    protected void doCheckInitialConditions(RefactoringStatus status, IProgressMonitor pm)
158
        throws org.eclipse.rephraserengine.core.vpg.refactoring.VPGRefactoring.PreconditionFailure
159
    {
160
        ensureProjectHasRefactoringEnabled(status);
161
162
        ensureSubroutineIsSelected();
163
164
        if (!matchingDeclarationsInInterfacesUniquelyBind())
165
            status
166
                .addWarning(Messages.AddSubroutineParameterRefactoring_matchingDeclarationsDoNotUniquelyBind);
167
168
        oldParameterList = getSubroutineParameters();
169
    }
170
171
    /*
172
     * By looking at the AST tree, starting at the node supplied to the refactoring as the selected
173
     * node, this method determines if a subroutine node has been selected or not.
174
     */
175
    private void ensureSubroutineIsSelected()
176
        throws org.eclipse.rephraserengine.core.vpg.refactoring.VPGRefactoring.PreconditionFailure
177
    {
178
        IASTNode temporaryNode = findEnclosingNode(astOfFileInEditor, selectedRegionInEditor);
179
180
        if (temporaryNode == null)
181
            fail(Messages.AddSubroutineParameterRefactoring_selectSubroutineError);
182
183
        if (temporaryNode instanceof ASTSubroutineSubprogramNode)
184
            selectedSubroutine = ((ASTSubroutineSubprogramNode)temporaryNode).getSubroutineStmt();
185
        else if (temporaryNode instanceof ASTSubroutineStmtNode)
186
        {
187
            if (temporaryNode.findNearestAncestor(ASTSubroutineSubprogramNode.class) == null)
188
                fail(Messages.AddSubroutineParameterRefactoring_selectSubroutineError);
189
            selectedSubroutine = (ASTSubroutineStmtNode)temporaryNode;
190
        }
191
        else
192
            fail(Messages.AddSubroutineParameterRefactoring_selectSubroutineError);
193
    }
194
195
    /*
196
     * This method determines if a matching declaration already exists in scope, and if so, will
197
     * fail the refactoring.
198
     */
199
    private boolean matchingDeclarationsInInterfacesUniquelyBind()
200
    {
201
        for (Definition declaration : getInterfaceDeclarations())
202
            if (declaration.resolveInterfaceBinding().size() != 1) return false;
203
204
        return true;
205
    }
206
207
    /*
208
     * (non-Javadoc)
209
     * 
210
     * @see
211
     * org.eclipse.rephraserengine.core.vpg.refactoring.VPGRefactoring#doCheckFinalConditions(org
212
     * .eclipse.ltk.core.refactoring.RefactoringStatus, org.eclipse.core.runtime.IProgressMonitor)
213
     */
214
    @Override
215
    protected void doCheckFinalConditions(RefactoringStatus status, IProgressMonitor pm)
216
        throws org.eclipse.rephraserengine.core.vpg.refactoring.VPGRefactoring.PreconditionFailure
217
    {
218
        ensureDeclarationIsValid();
219
220
        parameterName = declStmt.getEntityDeclList().get(0).getObjectName().getObjectName()
221
            .getText();
222
223
        ensurePositionIsValid();
224
225
        ensureDefaultValueIsValid();
226
227
        checkForConflictingBindings(pm, status);
228
    }
229
230
    /*
231
     * This method ensures that the default value supplied is valid by applying logic that tests
232
     * whether or not the default type supplied matches the type supplied in the declaration line.
233
     * For example, .true. and .false. are reserved for logical types. This method also ensures that
234
     * the default value is not a variable name beginning with a number.
235
     */
236
    private void ensureDefaultValueIsValid()
237
        throws org.eclipse.rephraserengine.core.vpg.refactoring.VPGRefactoring.PreconditionFailure
238
    {
239
        if (defaultValue == null || defaultValue.equals("") || //$NON-NLS-1$
240
            isWhiteSpace(defaultValue) || isVariableNameBeginningWithNumber(defaultValue)
241
            || (isTrueOrFalse(defaultValue) && !type.equals("logical")) || //$NON-NLS-1$
242
            (isANumber(defaultValue) && (!type.equals("integer") && !type.equals("real"))) || //$NON-NLS-1$//$NON-NLS-2$
243
            (isRealAndNotInteger(defaultValue) && type.equals("integer")) || //$NON-NLS-1$
244
            (defaultValue.equals("null") && !declaration.contains("pointer"))) //$NON-NLS-1$ //$NON-NLS-2$
245
            fail(Messages.AddSubroutineParameterRefactoring_InvalidDefaultValue);
246
    }
247
248
    /*
249
     * @param str A string to be tested
250
     * 
251
     * @return <code> true </code> if the selected string is a real number, and <code> false </code>
252
     * if the selected string is ann integer or not a number.
253
     */
254
    private boolean isRealAndNotInteger(String str)
255
    {
256
        if (isANumber(str))
257
        {
258
            try
259
            {
260
                Integer.parseInt(str);
261
            }
262
            catch (NumberFormatException e)
263
            {
264
                return true;
265
            }
266
        }
267
        return false;
268
    }
269
270
    /*
271
     * @param str A string to be tested
272
     * 
273
     * @return <code> true </code> if the selected string is ".true." or ".false.", and <code> false
274
     * </code> if the selected string is anything else.
275
     */
276
    private boolean isTrueOrFalse(String str)
277
    {
278
        if (str == null) return false;
279
        return str.equals(".true.") || str.equals(".false."); //$NON-NLS-1$ //$NON-NLS-2$
280
    }
281
282
    /*
283
     * @param str A string to be tested
284
     * 
285
     * @return <code> true </code> if the string begins with a number but is not a number (hence, a
286
     * variable name beginning with a number) and <code> false </code> otherwise.
287
     */
288
    private boolean isVariableNameBeginningWithNumber(String str)
289
    {
290
        if (str != null)
291
        {
292
            if (str.length() != 0)
293
            {
294
                if (isANumber(str.substring(0, 1)))
295
                {
296
                    if (!isANumber(str)) return true;
297
                }
298
            }
299
        }
300
301
        return false;
302
    }
303
304
    /*
305
     * @param str A string
306
     * 
307
     * @return <code> true </code> if str is a number.
308
     */
309
    private boolean isANumber(String str)
310
    {
311
        try
312
        {
313
            Double.parseDouble(str);
314
        }
315
        catch (NumberFormatException e)
316
        {
317
            return false;
318
        }
319
        return true;
320
    }
321
322
    /*
323
     * This function ensures that the position given to the refactoring is in bounds for the current
324
     * size of the list, and if not, fails the refactoring.
325
     */
326
    private void ensurePositionIsValid()
327
        throws org.eclipse.rephraserengine.core.vpg.refactoring.VPGRefactoring.PreconditionFailure
328
    {
329
        if (position > oldParameterList.size() || position < 0)
330
            fail(Messages.AddSubroutineParameterRefactoring_InvalidParameterPosition);
331
    }
332
333
    /*
334
     * This function attempts to produce a declaration node by passing the declaration line on to a
335
     * parser. If this node is returned as an error node, the refactoring fails.
336
     */
337
    private void ensureDeclarationIsValid()
338
        throws org.eclipse.rephraserengine.core.vpg.refactoring.VPGRefactoring.PreconditionFailure
339
    {
340
        IBodyConstruct decl = parseLiteralStatementNoFail(declaration);
341
        if (decl == null || !(decl instanceof ASTTypeDeclarationStmtNode))
342
            fail(Messages.AddSubroutineParameterRefactoring_InvalidDeclaration);
343
        declStmt = (ASTTypeDeclarationStmtNode)decl;
344
        IASTListNode<ASTEntityDeclNode> entityDeclList = declStmt.getEntityDeclList();
345
        if (entityDeclList == null)
346
        {
347
            fail(Messages.AddSubroutineParameterRefactoring_InvalidDeclaration);
348
        }
349
    }
350
351
    /*
352
     * This function checks to see whether or not the variable name supplied to the refactoring is
353
     * already in scope in the subroutine.
354
     */
355
    private void checkForConflictingBindings(IProgressMonitor pm, RefactoringStatus status)
356
    {
357
        Definition def = arbitraryDefinitionInScope();
358
        if (def == null) return; // No declarations in scope, so the new one can't conflict
359
360
        checkForConflictingBindings(pm, new ConflictingBindingErrorHandler(status), def,
361
            Collections.<PhotranTokenRef> emptyList(), parameterName);
362
    }
363
364
    /*
365
     * This function returns an arbitrary definition line in scope of the current node. It is used
366
     * to iterate through the declarations to see if there are any conflicts.
367
     */
368
    private Definition arbitraryDefinitionInScope()
369
    {
370
        ScopingNode enclosingScope = selectedSubroutine.findNearestAncestor(ScopingNode.class);
371
        List<Definition> allDefs = enclosingScope.getAllDefinitions();
372
        if (allDefs.isEmpty())
373
            return null;
374
        else
375
            return allDefs.get(0);
376
    }
377
378
    /*
379
     * @param str A string
380
     * 
381
     * @return <code> true </code> if str is only white space. This is used to test if default
382
     * values are nothing but white space.
383
     */
384
    private boolean isWhiteSpace(String str)
385
    {
386
        return str.replace(" ", "").replace("\t", "").equals(""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
387
    }
388
389
    /*
390
     * (non-Javadoc)
391
     * 
392
     * @see
393
     * org.eclipse.rephraserengine.core.vpg.refactoring.VPGRefactoring#doCreateChange(org.eclipse
394
     * .core.runtime.IProgressMonitor)
395
     */
396
    @Override
397
    protected void doCreateChange(IProgressMonitor pm) throws CoreException,
398
        OperationCanceledException
399
    {
400
401
        buildNewParameterListWithNewParameter();
402
403
        // Change the arguments list to the new list
404
        permuteArgumentList(selectedSubroutine);
405
406
        addArgumentDeclaration(selectedSubroutine);
407
408
        permuteCallSites();
409
410
        addChangeFromModifiedAST(fileInEditor, pm);
411
        vpg.releaseAST(fileInEditor);
412
413
    }
414
415
    /*
416
     * This function adds the declaration line to the subroutine.
417
     */
418
    private void addArgumentDeclaration(ASTSubroutineStmtNode subroutineStatement)
419
    {
420
        ASTSubroutineSubprogramNode subroutine = (ASTSubroutineSubprogramNode)subroutineStatement
421
            .getParent();
422
423
        IASTListNode<IBodyConstruct> statements = subroutine.getBody();
424
        if (statements == null)
425
        {
426
            statements = new ASTListNode<IBodyConstruct>();
427
            subroutine.setBody(statements);
428
        }
429
430
        statements.add(0, declStmt);
431
        Reindenter.reindent(declStmt, astOfFileInEditor);
432
433
    }
434
435
    /*
436
     * (non-Javadoc)
437
     * 
438
     * @see org.eclipse.ltk.core.refactoring.Refactoring#getName()
439
     */
440
    @Override
441
    public String getName()
442
    {
443
        return Messages.AddSubroutineParameterRefactoring_Name;
444
    }
445
446
    /*
447
     * This function returns the list of subroutine parameters from the selected subroutine node.
448
     */
449
    public List<ASTSubroutineParNode> getSubroutineParameters()
450
    {
451
        if (selectedSubroutine.getSubroutinePars() != null)
452
            return selectedSubroutine.getSubroutinePars();
453
454
        return new ArrayList<ASTSubroutineParNode>();
455
    }
456
457
    /*
458
     * This function returns a collection of interface declarations.
459
     */
460
    private Collection<Definition> getInterfaceDeclarations()
461
    {
462
        List<Definition> subroutineDefinitions = selectedSubroutine.getSubroutineName()
463
            .getSubroutineName().resolveBinding();
464
465
        if (subroutineDefinitions.size() != 1) return new ArrayList<Definition>();
466
467
        return subroutineDefinitions.get(0).findMatchingDeclarationsInInterfaces();
468
    }
469
470
    /*
471
     * This function builds the new parameter list to be supplied to the subroutine node by adding
472
     * the new parameter to the list in the appropriate position.
473
     */
474
    public void buildNewParameterListWithNewParameter()
475
    {
476
        // Create new variable
477
        ASTSubroutineParNode newParameter = new ASTSubroutineParNode();
478
        Token variableName = generateVariableName();
479
        newParameter.setVariableName(variableName);
480
481
        // Create new list
482
        newParameterList = new ArrayList<ASTSubroutineParNode>(oldParameterList);
483
        newParameterList.add(position, newParameter);
484
485
    }
486
487
    /*
488
     * This function returns a token for a variable with the name of the new parameter name.
489
     */
490
    private Token generateVariableName()
491
    {
492
        Token variableName = new Token(Terminal.T_IDENT, parameterName);
493
        return variableName;
494
    }
495
496
    /*
497
     * This function changes the argument list of the subroutine statement node to the new list
498
     * generated in buildNewParameterListWithNewParameter()
499
     */
500
    protected void permuteArgumentList(ASTSubroutineStmtNode node)
501
    {
502
        ASTSeparatedListNode<ASTSubroutineParNode> newParameterList = new ASTSeparatedListNode<ASTSubroutineParNode>(
503
            new Token(Terminal.T_COMMA, ","), this.newParameterList); //$NON-NLS-1$
504
        node.setSubroutinePars(newParameterList);
505
    }
506
507
    /*
508
     * This function changes all call sites to be updated to have the new argument in place, and
509
     * will match any calling pattern currently used.
510
     */
511
    private void permuteCallSites()
512
    {
513
        for (ASTCallStmtNode callStmt : getCallSites())
514
        {
515
            int previousArgumentListSize = 0;
516
517
            if (callStmt.getArgList() != null)
518
            {
519
                previousArgumentListSize = callStmt.getArgList().size();
520
            }
521
522
            // Generate new IExpression Node for the default value
523
            ASTIntConstNode expr = new ASTIntConstNode();
524
            expr.setIntConst(new Token(Terminal.T_ICON, defaultValue));
525
            ASTSubroutineArgNode addedParArg = new ASTSubroutineArgNode();
526
            addedParArg.setExpr(expr);
527
528
            // Test to see if the call site is using the
529
            // "(variableName = value, variablename = value)" pattern, or simply the
530
            // "(value, value)" pattern
531
            // The new parameter should follow this pattern at the call site, and should assume the
532
            // (value) pattern if the list was previously empty.
533
            if (previousArgumentListSize > 0)
534
            {
535
                int positionToCompareTo = Math.min(position, previousArgumentListSize - 1);
536
                ASTSubroutineParNode firstParameter = oldParameterList.get(positionToCompareTo);
537
                ASTSubroutineArgNode firstParameterArgument = getActualArgFromCallStmt(callStmt,
538
                    firstParameter.getVariableName(), positionToCompareTo);
539
                if (firstParameterArgument.getName() != null)
540
                    addedParArg.setName(new Token(Terminal.T_IDENT, parameterName));
541
            }
542
543
            ArrayList<ASTSubroutineArgNode> newParameterListForCallSite = new ArrayList<ASTSubroutineArgNode>();
544
545
            for (int i = 0; i < previousArgumentListSize; i++)
546
            {
547
                ASTSubroutineParNode desiredPar = oldParameterList.get(i);
548
                ASTSubroutineArgNode desiredParArgument = getActualArgFromCallStmt(callStmt,
549
                    desiredPar.getVariableName(), i);
550
                newParameterListForCallSite.add(desiredParArgument);
551
            }
552
553
            newParameterListForCallSite.add(position, addedParArg);
554
555
            ASTSeparatedListNode<ASTSubroutineArgNode> newArgList = new ASTSeparatedListNode<ASTSubroutineArgNode>(
556
                new Token(Terminal.T_COMMA, ","), newParameterListForCallSite); //$NON-NLS-1$
557
            callStmt.setArgList(newArgList);
558
        }
559
    }
560
561
    /*
562
     * This function returns the set of call sites for the subroutine that was selected.
563
     */
564
    private Set<ASTCallStmtNode> getCallSites()
565
    {
566
        List<Definition> subroutineDefinitions = selectedSubroutine.getSubroutineName()
567
            .getSubroutineName().resolveBinding();
568
        HashSet<ASTCallStmtNode> result = new HashSet<ASTCallStmtNode>();
569
570
        if (subroutineDefinitions.size() != 1) return result;
571
572
        for (PhotranTokenRef tokenRef : subroutineDefinitions.get(0).findAllReferences(true))
573
        {
574
            Token token = tokenRef.findToken();
575
576
            ASTCallStmtNode callStmtNode = token.findNearestAncestor(ASTCallStmtNode.class);
577
578
            if (callStmtNode != null) result.add(callStmtNode);
579
        }
580
581
        return result;
582
    }
583
584
    /*
585
     * This function gets an argument from a call statement, in order to check if it follows the
586
     * pattern of "Variablename = Value".
587
     */
588
    private ASTSubroutineArgNode getActualArgFromCallStmt(ASTCallStmtNode callStmt,
589
        Token desiredParName, int desiredParIndex)
590
    {
591
        for (int i = 0; i < callStmt.getArgList().size(); i++)
592
        {
593
            ASTSubroutineArgNode argument = callStmt.getArgList().get(i);
594
            if (argument.getName() == null || desiredParName == null)
595
            {
596
                if (i == desiredParIndex) return argument;
597
            }
598
            else
599
            {
600
                String argumentName = PhotranVPG.canonicalizeIdentifier(argument.getName()
601
                    .getText());
602
                String parameterName = PhotranVPG.canonicalizeIdentifier(desiredParName.getText());
603
                if (argumentName.equals(parameterName)) return argument;
604
            }
605
        }
606
        return null;
607
    }
608
609
    /*
610
     * This class handles all error cases for conflicting variable names or bindings.
611
     */
612
    private final class ConflictingBindingErrorHandler implements IConflictingBindingCallback
613
    {
614
        private final RefactoringStatus status;
615
616
        private ConflictingBindingErrorHandler(RefactoringStatus status)
617
        {
618
            this.status = status;
619
        }
620
621
        public void addConflictError(List<Conflict> conflictingDef)
622
        {
623
            Conflict conflict = conflictingDef.get(0);
624
625
            String msg = Messages.bind(
626
                Messages.AddSubroutineParameterRefactoring_NameConflictsWith, conflict.name,
627
                vpg.getDefinitionFor(conflict.tokenRef));
628
            RefactoringStatusContext context = createContext(conflict.tokenRef); // Highlights
629
                                                                                 // problematic
630
                                                                                 // definition
631
            status.addError(msg, context);
632
        }
633
634
        public void addConflictWarning(List<Conflict> conflictingDef)
635
        {
636
            Conflict conflict = conflictingDef.get(0);
637
638
            String msg = Messages.bind(
639
                Messages.AddSubroutineParameterRefactoring_NameMightConflictWithSubprogram,
640
                conflict.name);
641
            RefactoringStatusContext context = createContext(conflict.tokenRef); // Highlights
642
                                                                                 // problematic
643
                                                                                 // definition
644
            status.addWarning(msg, context);
645
        }
646
647
        public void addReferenceWillChangeError(String newName, Token reference)
648
        {
649
            throw new IllegalStateException();
650
        }
651
    }
652
653
}
(-)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 (+53 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 Joe Handzik, Joe Gonzales, Marc Celani, and Jason Patel.
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
 *    Joe Handzik, Joe Gonzales, Marc Celani, and Jason Patel - 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(), "Running Add Subroutine Parameter refactoring in", DIR,
38
            AddSubroutineParameterRefactoring.class);
39
    }
40
41
    @Override
42
    protected boolean configureRefactoring(AddSubroutineParameterRefactoring refactoring,
43
        IFile file, TextSelection selection, String[] markerText)
44
    {
45
        boolean shouldSucceed = super
46
            .configureRefactoring(refactoring, file, selection, markerText);
47
        refactoring.setDeclaration(markerText[4].replaceAll(";", ","));
48
        refactoring.setPosition(Integer.parseInt(markerText[5]));
49
        if (!markerText[6].equals("_dont_call")) refactoring.setDefaultValue(markerText[6]);
50
51
        return shouldSucceed;
52
    }
53
}
(-)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 (+175 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 Joe Handzik, Joe Gonzales, Marc Celani, and Jason Patel.
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
 *     Joe Handzik, Joe Gonzales, Marc Celani, and Jason Patel - 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
78
                protected Text locationField;
79
80
                protected Text defaultField;
81
82
                public void createControl(Composite parent)
83
                {
84
                    Composite group = new Composite(parent, SWT.NONE);
85
                    initializeDialogUnits(group);
86
                    setControl(group);
87
                    group.setLayout(new GridLayout(3, false));
88
89
                    GridData threeCol = new GridData();
90
                    threeCol.horizontalSpan = 3;
91
92
                    Label lbl = new Label(group, SWT.NONE);
93
                    lbl.setText(Messages.AddSubroutineParameterAction_DeclarationLabel);
94
                    Label lbl3 = new Label(group, SWT.NONE);
95
                    lbl3.setText(Messages.AddSubroutineParameterAction_DefaultLabel);
96
                    Label lbl2 = new Label(group, SWT.NONE);
97
                    lbl2.setText(Messages.AddSubroutineParameterAction_LocationLabel);
98
99
                    declField = new Text(group, SWT.BORDER);
100
                    declField.setText(addSubRefactoring.getDeclaration());
101
                    declField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
102
                    declField.selectAll();
103
                    declField.addModifyListener(new ModifyListener()
104
                    {
105
                        public void modifyText(ModifyEvent e)
106
                        {
107
                            addSubRefactoring.setDeclaration(declField.getText());
108
                        }
109
                    });
110
111
                    defaultField = new Text(group, SWT.BORDER);
112
                    defaultField.setText(addSubRefactoring.getDefault());
113
                    defaultField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
114
                    defaultField.selectAll();
115
                    defaultField.addModifyListener(new ModifyListener()
116
                    {
117
                        public void modifyText(ModifyEvent e)
118
                        {
119
                            addSubRefactoring.setDefaultValue(defaultField.getText());
120
                        }
121
                    });
122
123
                    locationField = new Text(group, SWT.BORDER);
124
                    locationField.setText(String.valueOf(addSubRefactoring.getPosition()));
125
                    locationField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
126
                    locationField.selectAll();
127
                    locationField.addModifyListener(new ModifyListener()
128
                    {
129
                        public void modifyText(ModifyEvent e)
130
                        {
131
                            addSubRefactoring.setPosition(Integer.parseInt(locationField.getText()));
132
                        }
133
                    });
134
135
                    // creates the table that lists the variables that exist in the subroutine
136
                    List<ASTSubroutineParNode> parList = addSubRefactoring.getOldParameterList();
137
138
                    GridData gridData = new GridData(GridData.VERTICAL_ALIGN_END);
139
                    gridData.horizontalSpan = 3;
140
                    gridData.horizontalAlignment = GridData.FILL;
141
142
                    Table table = new Table(group, SWT.BORDER);
143
                    table.setLinesVisible(true);
144
                    table.setHeaderVisible(true);
145
                    table.setLayoutData(gridData);
146
                    for (int i = 0; i < parList.size(); i++)
147
                    {
148
                        TableColumn column = new TableColumn(table, SWT.NONE);
149
                        column.setText(String.valueOf(i));
150
                    }
151
                    TableItem item = new TableItem(table, SWT.NONE);
152
                    for (int i = 0; i < parList.size(); i++)
153
                    {
154
                        item.setText(i, parList.get(i).getVariableName().getText());
155
                    }
156
                    for (int i = 0; i < parList.size(); i++)
157
                    {
158
                        table.getColumn(i).pack();
159
                    }
160
161
                    // Call once for sure, just in case the user doesn't modify the text
162
                    // addSubRefactoring.setDeclaration(declField.getText());
163
164
                    int offset = declField.getText().indexOf(":: "); //$NON-NLS-1$
165
                    if (offset < 0)
166
                        offset = 0;
167
                    else
168
                        offset = offset + ":: ".length(); //$NON-NLS-1$
169
                    declField.setSelection(offset, declField.getText().length());
170
                    declField.setFocus();
171
                }
172
            });
173
        }
174
    }
175
}
(-)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