Ejemplo n.º 1
0
        public FunctionDefinition(NameExpression name, Parameter[] parameters, Statement body, DecoratorStatement decorators = null) {
            if (name == null) {
                _name = new NameExpression("<lambda>");
                _isLambda = true;
            } else {
                _name = name;
            }

            _parameters = parameters;
            _body = body;
            _decorators = decorators;
        }
Ejemplo n.º 2
0
        public FunctionDefinition(NameExpression name, Parameter[] parameters, Statement body, DecoratorStatement decorators = null)
        {
            if (name == null)
            {
                _name     = new NameExpression("<lambda>");
                _isLambda = true;
            }
            else
            {
                _name = name;
            }

            _parameters = parameters;
            _body       = body;
            _decorators = decorators;
        }
Ejemplo n.º 3
0
        public ExtractMethodResult GetExtractionResult(ExtractMethodRequest info) {
            bool isStaticMethod = false, isClassMethod = false;
            var parameters = new List<Parameter>();
            string selfParam = null;
            if (info.TargetScope is ClassDefinition) {
                var fromScope = _scopes[_scopes.Length - 1] as FunctionDefinition;
                Debug.Assert(fromScope != null);  // we don't allow extracting from classes, so we have to be coming from a function
                if (fromScope != null) {
                    if (fromScope.Decorators != null) {
                        foreach (var decorator in fromScope.Decorators.Decorators) {
                            NameExpression name = decorator as NameExpression;
                            if (name != null) {
                                if (name.Name == "staticmethod") {
                                    isStaticMethod = true;
                                } else if (name.Name == "classmethod") {
                                    isClassMethod = true;
                                }
                            }
                        }
                    }

                    if (!isStaticMethod) {
                        if (fromScope.Parameters.Count > 0) {
                            selfParam = fromScope.Parameters[0].Name;
                            parameters.Add(new Parameter(selfParam, ParameterKind.Normal));
                        }
                    }
                }
            }

            foreach (var param in info.Parameters) {
                var newParam = new Parameter(param, ParameterKind.Normal);
                if (parameters.Count > 0) {
                    newParam.AddPreceedingWhiteSpace(_ast, " ");
                }
                parameters.Add(newParam);
            }

            // include any non-closed over parameters as well...
            foreach (var input in _inputVars) {
                var variableScope = input.Scope;
                var parentScope = info.TargetScope;

                // are these variables a child of the target scope so we can close over them?
                while (parentScope != null && parentScope != variableScope) {
                    parentScope = parentScope.Parent;
                }

                if (parentScope == null && input.Name != selfParam) {
                    // we can either close over or pass these in as parameters, add them to the list
                    var newParam = new Parameter(input.Name, ParameterKind.Normal);
                    if (parameters.Count > 0) {
                        newParam.AddPreceedingWhiteSpace(_ast, " ");
                    }
                    parameters.Add(newParam);
                }
            }

            var body = _target.GetBody(_ast);
            var isCoroutine = IsCoroutine(body);

            // reset leading indentation to single newline + indentation, this
            // strips out any proceeding comments which we don't extract
            var leading = _newline + body.GetIndentationLevel(_ast);
            body.SetLeadingWhiteSpace(_ast, leading);

            if (_outputVars.Count > 0) {
                // need to add a return statement
                Expression retValue;
                Expression[] names = new Expression[_outputVars.Count];
                int outputIndex = 0;
                foreach (var name in _outputVars) {
                    var nameExpr = new NameExpression(name.Name);
                    nameExpr.AddPreceedingWhiteSpace(_ast, " ");
                    names[outputIndex++] = nameExpr;
                }
                var tuple = new TupleExpression(false, names);
                tuple.RoundTripHasNoParenthesis(_ast);
                retValue = tuple;

                var retStmt = new ReturnStatement(retValue);
                retStmt.SetLeadingWhiteSpace(_ast, leading);

                body = new SuiteStatement(
                    new Statement[] { 
                        body,
                        retStmt
                    }
                );
            } else {
                // we need a SuiteStatement to give us our colon
                body = new SuiteStatement(new Statement[] { body });
            }

            DecoratorStatement decorators = null;
            if (isStaticMethod) {
                decorators = new DecoratorStatement(new[] { new NameExpression("staticmethod") });
            } else if (isClassMethod) {
                decorators = new DecoratorStatement(new[] { new NameExpression("classmethod") });
            }

            var res = new FunctionDefinition(new NameExpression(info.Name), parameters.ToArray(), body, decorators);
            res.IsCoroutine = isCoroutine;
            
            StringBuilder newCall = new StringBuilder();
            newCall.Append(_target.IndentationLevel);
            var method = res.ToCodeString(_ast);

            // fix up indentation...
            for (int curScope = 0; curScope < _scopes.Length; curScope++) {
                if (_scopes[curScope] == info.TargetScope) {
                    // this is our target indentation level.
                    var indentationLevel = _scopes[curScope].Body.GetIndentationLevel(_ast);
                    var lines = method.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);
                    int minWhiteSpace = Int32.MaxValue;
                    for (int curLine = decorators == null ? 1 : 2; curLine < lines.Length; curLine++) {
                        var line = lines[curLine];

                        for (int i = 0; i < line.Length; i++) {
                            if (!Char.IsWhiteSpace(line[i])) {
                                minWhiteSpace = Math.Min(minWhiteSpace, i);
                                break;
                            }
                        }
                    }

                    StringBuilder newLines = new StringBuilder();
                    newLines.Append(indentationLevel);
                    newLines.Append(lines[0]);
                    if (decorators != null) {
                        newLines.Append(_newline);
                        newLines.Append(indentationLevel);
                        newLines.Append(lines[1]);
                    }

                    // don't include a bunch of blank lines...
                    int endLine = lines.Length - 1;
                    for (; endLine >= 0 && String.IsNullOrWhiteSpace(lines[endLine]); endLine--) {
                    }

                    newLines.Append(_newline);
                    for (int curLine = decorators == null ? 1 : 2; curLine <= endLine; curLine++) {
                        var line = lines[curLine];

                        newLines.Append(indentationLevel);
                        if (_insertTabs) {
                            newLines.Append('\t');
                        } else {
                            newLines.Append(' ', _indentSize);
                        }

                        if (line.Length > minWhiteSpace) {
                            newLines.Append(line, minWhiteSpace, line.Length - minWhiteSpace);
                        }
                        newLines.Append(_newline);
                    }
                    newLines.Append(_newline);
                    method = newLines.ToString();
                    break;
                }
            }

            string comma;
            if (_outputVars.Count > 0) {
                comma = "";
                foreach (var outputVar in _outputVars) {
                    newCall.Append(comma);
                    newCall.Append(outputVar.Name);
                    comma = ", ";
                }
                newCall.Append(" = ");
            } else if (_target.ContainsReturn) {
                newCall.Append("return ");
            }

            if (isCoroutine) {
                newCall.Append("await ");
            }

            if (info.TargetScope is ClassDefinition) {
                var fromScope = _scopes[_scopes.Length - 1] as FunctionDefinition;
                Debug.Assert(fromScope != null);  // we don't allow extracting from classes, so we have to be coming from a function

                if (isStaticMethod) {
                    newCall.Append(info.TargetScope.Name);
                    newCall.Append('.');
                } else if (fromScope != null && fromScope.Parameters.Count > 0) {
                    newCall.Append(fromScope.Parameters[0].Name);
                    newCall.Append('.');
                }
            }

            newCall.Append(info.Name);
            newCall.Append('(');

            comma = "";
            foreach (var param in parameters) {
                if (param.Name != selfParam) {
                    newCall.Append(comma);
                    newCall.Append(param.Name);
                    comma = ", ";
                }
            }

            newCall.Append(')');

            return new ExtractMethodResult(
                method,
                newCall.ToString()
            );
        }
Ejemplo n.º 4
0
        //  decorators ::=
        //      decorator+
        //  decorator ::=
        //      "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE
        private DecoratorStatement ParseDecorators(out List<string> newlineWhiteSpace) {
            List<Expression> decorators = new List<Expression>();
            newlineWhiteSpace = MakeWhiteSpaceList();
            Eat(TokenKind.At);
            var decStart = GetStart();
            do {
                if (newlineWhiteSpace != null) {
                    newlineWhiteSpace.Add(_tokenWhiteSpace);
                }
                var start = GetStart();
                var name = ReadName();
                Expression decorator = MakeName(name);
                if (!name.HasName) {
                    decorators.Add(null);
                    continue;
                }

                if (_verbatim) {
                    AddPreceedingWhiteSpace(decorator, _tokenWhiteSpace);
                }
                decorator.SetLoc(GetStart(), GetEnd());
                while (MaybeEat(TokenKind.Dot)) {
                    string whitespace = _tokenWhiteSpace;
                    name = ReadNameMaybeNone();
                    if (!name.HasName) {
                        decorator = Error(_verbatim ? (_tokenWhiteSpace + _token.Token.VerbatimImage + _lookaheadWhiteSpace + _lookahead.Token.VerbatimImage) : null, decorator);
                        NextToken();
                    } else {
                        string nameWhitespace = _tokenWhiteSpace;
                        var memberDecorator = MakeMember(decorator, name);
                        memberDecorator.SetLoc(start, GetStart(), GetEnd());
                        if (_verbatim) {
                            AddPreceedingWhiteSpace(memberDecorator, whitespace);
                            AddSecondPreceedingWhiteSpace(memberDecorator, nameWhitespace);
                        }

                        decorator = memberDecorator;
                    }
                }

                if (MaybeEat(TokenKind.LeftParenthesis)) {
                    string parenWhiteSpace = _tokenWhiteSpace;
                    var commaWhiteSpace = MakeWhiteSpaceList();
                    bool ateTerminator;
                    Arg[] args = FinishArgumentList(null, commaWhiteSpace, out ateTerminator);
                    decorator = FinishCallExpr(decorator, args);

                    if (_verbatim) {
                        AddPreceedingWhiteSpace(decorator, parenWhiteSpace);
                        AddSecondPreceedingWhiteSpace(decorator, _tokenWhiteSpace);
                        if (commaWhiteSpace != null) {
                            AddListWhiteSpace(decorator, commaWhiteSpace.ToArray());
                        }
                        if (!ateTerminator) {
                            AddErrorMissingCloseGrouping(decorator);
                        }
                    }
                    decorator.SetLoc(start, GetEnd());
                }

                string newline;
                EatNewLine(out newline);
                if (newlineWhiteSpace != null) {
                    newlineWhiteSpace.Add(newline);
                }

                decorators.Add(decorator);
            } while (MaybeEat(TokenKind.At));
             
            var res = new DecoratorStatement(decorators.ToArray());
            res.SetLoc(decStart, GetEnd());
            return res;
        }
Ejemplo n.º 5
0
 private static void CheckDecorators(Action<Expression>[] decorators, DecoratorStatement foundDecorators) {
     if (decorators != null) {
         Assert.AreEqual(decorators.Length, foundDecorators.Decorators.Count);
         for (int i = 0; i < decorators.Length; i++) {
             decorators[i](foundDecorators.Decorators[i]);
         }
     } else {
         Assert.AreEqual(null, foundDecorators);
     }
 }
Ejemplo n.º 6
0
 public override void PostWalk(DecoratorStatement node) { PostWalkWorker(node); }
Ejemplo n.º 7
0
 // DecoratorStatement
 public override bool Walk(DecoratorStatement node) { return ShouldWalkWorker(node); }
Ejemplo n.º 8
0
        private void AddTagIfNecessary(int startIndex, int endIndex, int headerIndex = -1, DecoratorStatement decorator = null, int minLinesToCollapse = 3) {
            var startLine = _ast.IndexToLocation(startIndex).Line;
            var endLine = _ast.IndexToLocation(endIndex).Line;
            var lines = endLine - startLine + 1;

            // Collapse if more than 3 lines.
            if (lines >= minLinesToCollapse) {
                if (decorator != null) {
                    // we don't want to collapse the decorators, we like them visible, so
                    // we base our starting position on where the decorators end.
                    startIndex = decorator.EndIndex + 1;
                }

                var tagSpan = new AP.OutliningTag() {
                    startIndex = startIndex,
                    endIndex = endIndex,
                    headerIndex = headerIndex
                };
                TagSpans.Add(tagSpan);
            }
        }
Ejemplo n.º 9
0
 private void AddTagIfNecessary(Node node, int headerIndex = -1, DecoratorStatement decorator = null) {
     AddTagIfNecessary(node.StartIndex, node.EndIndex, headerIndex, decorator);
 }