Esempio n. 1
0
        private bool ParseDollar(TemplateStream stream, TokenList tokens, ContextStack context, ScopeStack scope)
        {
            if (stream.Current != '$' || scope.Current == Scope.Block)
            {
                return(false);
            }

            var next = stream.Peek();

            if (next == '$')
            {
                stream.Advance(2);
                return(true);
            }

            if (char.IsLetter(next))
            {
                scope.Push(Scope.Statement);
                stream.Advance();
                return(true);
            }

            if (next == '{')
            {
                scope.Push(Scope.Block);
                stream.Advance();
                return(true);
            }

            return(false);
        }
Esempio n. 2
0
        private bool ParseStatement(TemplateStream stream, TokenList tokens, ContextStack context, ScopeStack scope)
        {
            if (scope.Current == Scope.Statement)
            {
                scope.Pop();
            }
            else if (scope.Current == Scope.Block)
            {
                var previous = stream.Peek(-1);
                if (previous == '$' || char.IsLetterOrDigit(previous))
                {
                    return(false);
                }
            }
            else
            {
                return(false);
            }

            var name       = stream.PeekWord();
            var identifier = context.Current.GetIdentifier(name);

            if (identifier != null)
            {
                tokens.Add(new Token(stream.Position, name.Length, stream.Line, TokenType.Identifier, context.Current, identifier.QuickInfo));
                stream.Advance(name.Length);

                if (identifier.Type == IdentifierType.Indexed)
                {
                    if (stream.Current == '(')
                    {
                        scope.Push(Scope.Filter);
                    }
                    if (stream.Current == '[')
                    {
                        scope.Push(Scope.Template);
                        context.Push(name, stream.Position);
                    }
                }
                else if (identifier.Type == IdentifierType.Boolean)
                {
                    if (stream.Current == '[')
                    {
                        scope.Push(Scope.True);
                    }
                }

                return(true);
            }

            return(false);
        }
 public ILGenerationContext()
 {
     Output = new ILOutputStream();
     ScopeStack = new ScopeStack();
     ILScope globalScope = new ILScope();
     ScopeStack.Push(globalScope);
 }
        protected void InitializeScope(string scopeName, DbConnection connection, bool keepOpen)
        {
            this.ScopeName = scopeName;
            ScopeStack.Push(this);

            InitializeConnection(connection, keepOpen);
        }
Esempio n. 5
0
        /// <summary>
        /// Leave this context scope.  The context
        /// will then be the next last one on the stack.
        /// </summary>
        public void Leave()
        {
            if (!_hasLeft)
            {
                //  Remove it from stack
                if (ScopeStack == null || ScopeStack.Count == 0)
                {
                    throw new InvalidOperationException("Error when trying to leave an unknown context scope.");
                }

                Scope <T> delScope = ScopeStack.Pop();

                if (!delScope.Equals(this))
                {
                    //  This context scope is not at the top of the stack.
                    ScopeStack.Push(delScope);

                    throw new InvalidOperationException("This context scope is not at the top of the stack.");
                }
                if (_isDisposable)
                {
                    Release();
                }

                //  Clean up the stack object if it is empty
                if (ScopeStack.Count == 0)
                {
                    ScopeStack = null;
                }
            }
            _hasLeft = true;
        }
Esempio n. 6
0
        public void ReadObject()
        {
            if (_scopeStack.Count > 0)
            {
                ValidateValue();
            }

            if (_c != '{')
            {
                throw new Exception("Expected '{'.");
            }

            _c = (char)_reader.Read();
            ParseWhiteSpace();

            _scopeStack.Push(new Scope(ScopeType.Object));
        }
        /// <summary>
        /// Creates a new <see cref="TimedScope"/>, logs start info and starts the stopwatch.
        /// </summary>
        /// <param name="loggingScope">Logging scope to be used - the reported scope name comes form <see cref="LoggingScope.Module"/> property.</param>
        /// <param name="startWith">Initial result status - use <see cref="Status.Failure"/> when the action may throw.</param>
        /// <remarks>Use a <c>using</c> block when possible, otherwise you have to remember to call <see cref="Dispose"/>.</remarks>
        public TimedScope(LoggingScope loggingScope, Status startWith = Status.Success)
        {
            LoggingScope = loggingScope;
            Result       = startWith;
            ScopeStack   = ScopeStack.Push(this);

            LoggingScope.Info("TimedScope started.");
            Stopwatch = Stopwatch.StartNew();
        }
        protected void InitializeScope(string scopeName, string configuration)
        {
            this.ScopeName = scopeName;
            ScopeStack.Push(this);

            var connection = Connector.Connect(configuration);

            InitializeConnection(connection, false);
        }
Esempio n. 9
0
        /// <summary>
        /// Writes the start of an object
        /// </summary>
        public JsonWriter WriteStartObject()
        {
            if (_scopeStack.Count > 0)
            {
                Scope scope = _scopeStack.Peek();
                if ((scope.ScopeType == ScopeType.Object) && (!scope.NameWritten))
                {
                    throw new Exception("Must write a name before creating a nested object.");
                }

                // When writing an array of objects we separate them with commas
                WriteComma();
            }

            _scopeStack.Push(new Scope(ScopeType.Object));
            _writer.Write('{');

            return(this);
        }
Esempio n. 10
0
 private void ConfigCurrentScope()
 {
     if (_Current != null)
     {
         // if exists current scope, push it in stack
         ScopeStack.Push(_Current);
     }
     _Current      = this;
     InstanceCount = 1;
     //Iniyialize all scope contexts
     Array.ForEach(ScopeContexts.Values.ToArray(), (scopeContext => scopeContext.Init()));
 }
Esempio n. 11
0
        public Scope(T context, bool isDisposable)
        {
            _isDisposable = isDisposable;
            Context       = context;

            if (ScopeStack == null)
            {
                ScopeStack = new Stack <Scope <T> >();
            }

            ScopeStack.Push(this);
        }
        protected void InitializeScope(string scopeName)
        {
            this.ScopeName = scopeName;
            ScopeStack.Push(this);

            var primaryScope = ScopeBag[scopeName];

            if (primaryScope == null)
            {
                throw new NoConnectionException(
                          "O construtor do SequelScope sem configuração ou nome de conexão deve ser executado "
                          + "dentro de um escopo de SequelScope previamente aberto."
                          );
            }
            InitializeConnection(primaryScope.connection, true);
        }
Esempio n. 13
0
        internal override void AnalyzeNode()
        {
            // get the name of this function, calculate something if it's anonymous
            m_name = (m_identifier == null ? GuessAtName() : m_identifier.Name);

            // don't analyze the identifier or we'll add an extra reference to it.
            // and we don't need to analyze the parameters because they were fielded-up
            // back when the function object was created, too

            // push the stack and analyze the body
            ScopeStack.Push(m_functionScope);
            try
            {
                // recurse
                base.AnalyzeNode();
            }
            finally
            {
                ScopeStack.Pop();
            }
        }
        /// <summary>
        /// Get instance of the parent delta feed scope
        /// </summary>
        /// <returns>
        /// The parent delta feed scope
        /// Or null if there is no parent delta feed scope
        /// </returns>
        private DeltaFeedScope GetParentDeltaFeedScope()
        {
            ScopeStack scopeStack = new ScopeStack();
            Scope parentFeedScope = null;

            if (this.scopes.Count > 0)
            {
                // pop current scope and push into scope stack
                scopeStack.Push(this.scopes.Pop());
            }

            while (this.scopes.Count > 0)
            {
                Scope scope = this.scopes.Pop();
                scopeStack.Push(scope);

                if (scope is DeltaFeedScope)
                {
                    parentFeedScope = scope;
                    break;
                }
            }

            while (scopeStack.Count > 0)
            {
                Scope scope = scopeStack.Pop();
                this.scopes.Push(scope);
            }

            return parentFeedScope as DeltaFeedScope;
        }
Esempio n. 15
0
        /// <summary>
        /// Get instance of the parent entry scope
        /// </summary>
        /// <returns>
        /// The parent entry scope
        /// Or null if there is no parent entry scope
        /// </returns>
        protected EntryScope GetParentEntryScope()
        {
            ScopeStack scopeStack = new ScopeStack();
            Scope parentEntryScope = null;

            if (this.scopes.Count > 0)
            {
                // pop current scope and push into scope stack
                scopeStack.Push(this.scopes.Pop());
            }

            while (this.scopes.Count > 0)
            {
                Scope scope = this.scopes.Pop();
                scopeStack.Push(scope);

                if (scope is EntryScope)
                {
                    parentEntryScope = scope;
                    break;
                }
            }

            while (scopeStack.Count > 0)
            {
                Scope scope = scopeStack.Pop();
                this.scopes.Push(scope);
            }

            return parentEntryScope as EntryScope;
        }
Esempio n. 16
0
        private bool ParseDollar(TemplateStream stream, TokenList tokens, ContextStack context, ScopeStack scope)
        {
            if (stream.Current != '$' || scope.Current == Scope.Block) return false;

            var next = stream.Peek();
            if (next == '$')
            {
                stream.Advance(2);
                return true;
            }

            if (char.IsLetter(next))
            {
                scope.Push(Scope.Statement);
                stream.Advance();
                return true;
            }

            if (next == '{')
            {
                scope.Push(Scope.Block);
                stream.Advance();
                return true;
            }

            return false;
        }
Esempio n. 17
0
        private bool ParseOther(TemplateStream stream, TokenList tokens, ContextStack context, ScopeStack scope, BraceStack brace)
        {
            switch (stream.Current)
            {
                case '[':
                    brace.Push(tokens.Add(new Token(stream.Position, 1, stream.Line, TokenType.OpenBrace, context.Current)), scope.Changed);
                    stream.Advance();
                    return true;

                case ']':
                    var openBrace = brace.Pop(TokenType.OpenBrace);
                    var token = tokens.Add(new Token(stream.Position, 1, stream.Line, TokenType.CloseBrace, context.Current, null, openBrace.Token));
                    if (openBrace.Token != null)
                    {
                        openBrace.Token.MatchingToken = token;
                    }
                    stream.Advance();

                    if (openBrace.ScopeChanged)
                    {
                        var current = scope.Pop();
                        if (current == Scope.Template)
                        {
                            context.Pop(stream.Position);
                            if (stream.Current == '[') scope.Push(Scope.Separator);
                        }
                        else if (current == Scope.True)
                        {
                            context.Pop(stream.Position);
                            if (stream.Current == '[') scope.Push(Scope.False);
                        }
                    }
                    return true;

                case '{':
                    //tokens.Add(new Token(stream.Position - 1, 2, TokenType.OpenBlock, context.Current));
                    brace.Push(tokens.Add(new Token(stream.Position, 1, stream.Line, TokenType.OpenCurlyBrace, context.Current)), scope.Changed);
                    stream.Advance();
                    return true;

                case '}':
                    var openCurlyBrace = brace.Pop(TokenType.OpenCurlyBrace);
                    token = tokens.Add(new Token(stream.Position, 1, stream.Line, TokenType.CloseCurlyBrace, context.Current, null, openCurlyBrace.Token));
                    if (openCurlyBrace.Token != null)
                    {
                        openCurlyBrace.Token.MatchingToken = token;
                    }
                    //tokens.Add(new Token(stream.Position, 1, TokenType.CloseBlock, context.Current));
                    stream.Advance();

                    if (openCurlyBrace.ScopeChanged)
                    {
                        scope.Pop();
                    }
                    return true;

                case '(':
                    brace.Push(tokens.Add(new Token(stream.Position, 1, stream.Line, TokenType.OpenFunctionBrace, context.Current)), scope.Changed);
                    stream.Advance();
                    return true;

                case ')':
                    var openFunctionBrace = brace.Pop(TokenType.OpenFunctionBrace);
                    token = tokens.Add(new Token(stream.Position, 1, stream.Line, TokenType.CloseFunctionBrace, context.Current, null, openFunctionBrace.Token));
                    if (openFunctionBrace.Token != null)
                    {
                        openFunctionBrace.Token.MatchingToken = token;
                    }
                    stream.Advance();

                    if (openFunctionBrace.ScopeChanged)
                    {
                        scope.Pop();
                    }
                    return true;
            }

            if (scope.Current == Scope.Block) return false;

            var name = stream.PeekWord();

            if (name == null) return false;

            if (keywords.Contains(name))
            {
                tokens.Add(new Token(stream.Position, name.Length, stream.Line, TokenType.Keyword, context.Current));
            }

            stream.Advance(name.Length);
            return true;
        }
Esempio n. 18
0
        private bool ParseStatement(TemplateStream stream, TokenList tokens, ContextStack context, ScopeStack scope)
        {
            if (scope.Current == Scope.Statement)
            {
                scope.Pop();
            }
            else if (scope.Current == Scope.Block)
            {
                var previous = stream.Peek(-1);
                if (previous == '$' || char.IsLetterOrDigit(previous)) return false;
            }
            else
            {
                return false;
            }

            var name = stream.PeekWord();
            var identifier = context.Current.GetIdentifier(name);

            if (identifier != null)
            {
                tokens.Add(new Token(stream.Position, name.Length, stream.Line, TokenType.Identifier, context.Current, identifier.QuickInfo));
                stream.Advance(name.Length);

                if (identifier.Type == IdentifierType.Indexed)
                {
                    if (stream.Current == '(') scope.Push(Scope.Filter);
                    if (stream.Current == '[')
                    {
                        scope.Push(Scope.Template);
                        context.Push(name, stream.Position);
                    }
                }
                else if (identifier.Type == IdentifierType.Boolean)
                {
                    if (stream.Current == '[') scope.Push(Scope.True);
                }

                return true;
            }

            return false;
        }
        Dictionary <string, ScopeStack> GetClassificationMap(string scope)
        {
            Dictionary <string, ScopeStack> result;
            var baseScopeStack = new ScopeStack(scope);

            defaultScopeStack = baseScopeStack.Push(EditorThemeColors.Foreground);
            if (classificationMapCache.TryGetValue(scope, out result))
            {
                return(result);
            }
            result = new Dictionary <string, ScopeStack> {
                [ClassificationTypeNames.Comment]             = MakeScope(baseScopeStack, "comment." + scope),
                [ClassificationTypeNames.ExcludedCode]        = MakeScope(baseScopeStack, "comment.excluded." + scope),
                [ClassificationTypeNames.Identifier]          = MakeScope(baseScopeStack, scope),
                [ClassificationTypeNames.Keyword]             = MakeScope(baseScopeStack, "keyword." + scope),
                ["identifier - keyword - (TRANSIENT)"]        = MakeScope(baseScopeStack, "keyword." + scope), // required for highlighting of some context specific keywords like 'nameof'
                [ClassificationTypeNames.NumericLiteral]      = MakeScope(baseScopeStack, "constant.numeric." + scope),
                [ClassificationTypeNames.Operator]            = MakeScope(baseScopeStack, scope),
                [ClassificationTypeNames.PreprocessorKeyword] = MakeScope(baseScopeStack, "meta.preprocessor." + scope),
                [ClassificationTypeNames.StringLiteral]       = MakeScope(baseScopeStack, "string." + scope),
                [ClassificationTypeNames.WhiteSpace]          = MakeScope(baseScopeStack, "text." + scope),
                [ClassificationTypeNames.Text] = MakeScope(baseScopeStack, "text." + scope),

                [ClassificationTypeNames.PreprocessorText]      = MakeScope(baseScopeStack, "meta.preprocessor.region.name." + scope),
                [ClassificationTypeNames.Punctuation]           = MakeScope(baseScopeStack, "punctuation." + scope),
                [ClassificationTypeNames.VerbatimStringLiteral] = MakeScope(baseScopeStack, "string.verbatim." + scope),

                [ClassificationTypeNames.ClassName]         = MakeScope(baseScopeStack, "entity.name.class." + scope),
                [ClassificationTypeNames.DelegateName]      = MakeScope(baseScopeStack, "entity.name.delegate." + scope),
                [ClassificationTypeNames.EnumName]          = MakeScope(baseScopeStack, "entity.name.enum." + scope),
                [ClassificationTypeNames.InterfaceName]     = MakeScope(baseScopeStack, "entity.name.interface." + scope),
                [ClassificationTypeNames.ModuleName]        = MakeScope(baseScopeStack, "entity.name.module." + scope),
                [ClassificationTypeNames.StructName]        = MakeScope(baseScopeStack, "entity.name.struct." + scope),
                [ClassificationTypeNames.TypeParameterName] = MakeScope(baseScopeStack, "entity.name.typeparameter." + scope),

                [ClassificationTypeNames.FieldName]           = MakeScope(baseScopeStack, "entity.name.field." + scope),
                [ClassificationTypeNames.EnumMemberName]      = MakeScope(baseScopeStack, "entity.name.enummember." + scope),
                [ClassificationTypeNames.ConstantName]        = MakeScope(baseScopeStack, "entity.name.constant." + scope),
                [ClassificationTypeNames.LocalName]           = MakeScope(baseScopeStack, "entity.name.local." + scope),
                [ClassificationTypeNames.ParameterName]       = MakeScope(baseScopeStack, "entity.name.parameter." + scope),
                [ClassificationTypeNames.ExtensionMethodName] = MakeScope(baseScopeStack, "entity.name.extensionmethod." + scope),
                [ClassificationTypeNames.MethodName]          = MakeScope(baseScopeStack, "entity.name.function." + scope),
                [ClassificationTypeNames.PropertyName]        = MakeScope(baseScopeStack, "entity.name.property." + scope),
                [ClassificationTypeNames.EventName]           = MakeScope(baseScopeStack, "entity.name.event." + scope),

                [ClassificationTypeNames.XmlDocCommentAttributeName]         = MakeScope(baseScopeStack, "comment.line.documentation." + scope),
                [ClassificationTypeNames.XmlDocCommentAttributeQuotes]       = MakeScope(baseScopeStack, "comment.line.documentation." + scope),
                [ClassificationTypeNames.XmlDocCommentAttributeValue]        = MakeScope(baseScopeStack, "comment.line.documentation." + scope),
                [ClassificationTypeNames.XmlDocCommentCDataSection]          = MakeScope(baseScopeStack, "comment.line.documentation." + scope),
                [ClassificationTypeNames.XmlDocCommentComment]               = MakeScope(baseScopeStack, "comment.line.documentation." + scope),
                [ClassificationTypeNames.XmlDocCommentDelimiter]             = MakeScope(baseScopeStack, "comment.line.documentation.delimiter." + scope),
                [ClassificationTypeNames.XmlDocCommentEntityReference]       = MakeScope(baseScopeStack, "comment.line.documentation." + scope),
                [ClassificationTypeNames.XmlDocCommentName]                  = MakeScope(baseScopeStack, "comment.line.documentation." + scope),
                [ClassificationTypeNames.XmlDocCommentProcessingInstruction] = MakeScope(baseScopeStack, "comment.line.documentation." + scope),
                [ClassificationTypeNames.XmlDocCommentText]                  = MakeScope(baseScopeStack, "comment.line.documentation." + scope),

                [ClassificationTypeNames.XmlLiteralAttributeName]      = MakeScope(baseScopeStack, "entity.other.attribute-name." + scope),
                [ClassificationTypeNames.XmlLiteralAttributeQuotes]    = MakeScope(baseScopeStack, "punctuation.definition.string." + scope),
                [ClassificationTypeNames.XmlLiteralAttributeValue]     = MakeScope(baseScopeStack, "string.quoted." + scope),
                [ClassificationTypeNames.XmlLiteralCDataSection]       = MakeScope(baseScopeStack, "text." + scope),
                [ClassificationTypeNames.XmlLiteralComment]            = MakeScope(baseScopeStack, "comment.block." + scope),
                [ClassificationTypeNames.XmlLiteralDelimiter]          = MakeScope(baseScopeStack, scope),
                [ClassificationTypeNames.XmlLiteralEmbeddedExpression] = MakeScope(baseScopeStack, scope),
                [ClassificationTypeNames.XmlLiteralEntityReference]    = MakeScope(baseScopeStack, scope),
                [ClassificationTypeNames.XmlLiteralName] = MakeScope(baseScopeStack, "entity.name.tag.localname." + scope),
                [ClassificationTypeNames.XmlLiteralProcessingInstruction] = MakeScope(baseScopeStack, scope),
                [ClassificationTypeNames.XmlLiteralText] = MakeScope(baseScopeStack, "text." + scope),
            };
            classificationMapCache = classificationMapCache.SetItem(scope, result);

            return(result);
        }
 static ScopeStack MakeScope(ScopeStack defaultScope, string scope)
 {
     return(defaultScope.Push(scope));
 }
        void ScanAndAddComment(List <ColoredSegment> coloredSegments, int startOffset, ScopeStack commentScopeStack, ClassificationSpan classificationSpan)
        {
            int lastClassifiedOffset = classificationSpan.Span.Start;

            try {
                // Scan comments for tag highlighting
                var text = textView.TextSnapshot.GetText(classificationSpan.Span);
                int idx = 0, oldIdx = 0;

                while ((idx = FindNextCommentTagIndex(text, idx, out string commentTag)) >= 0)
                {
                    var headSpanLength = idx - oldIdx;
                    if (headSpanLength > 0)
                    {
                        var headSegment = new ColoredSegment(lastClassifiedOffset - startOffset, headSpanLength, commentScopeStack);
                        lastClassifiedOffset += headSpanLength;
                        coloredSegments.Add(headSegment);
                    }
                    var highlightSegment = new ColoredSegment(lastClassifiedOffset - startOffset, commentTag.Length, commentScopeStack.Push("markup.other"));
                    coloredSegments.Add(highlightSegment);
                    idx += commentTag.Length;
                    lastClassifiedOffset += commentTag.Length;
                    oldIdx = idx;
                }
            } catch (Exception e) {
                LoggingService.LogError("Error while scanning comment tags.", e);
            }
            int tailSpanLength = classificationSpan.Span.End - lastClassifiedOffset;

            if (tailSpanLength > 0)
            {
                var tailSpan = new ColoredSegment(lastClassifiedOffset - startOffset, tailSpanLength, commentScopeStack);
                coloredSegments.Add(tailSpan);
            }
        }
Esempio n. 22
0
 private void BeginScope()
 {
     _scopes.Push(new Dictionary <string, Resolution>());
 }
Esempio n. 23
0
        internal override void AnalyzeNode()
        {
            // javascript doesn't have block scope, so there really is no point
            // in nesting blocks. Unnest any now, before we start combining var statements
            UnnestBlocks();

            // if we want to remove debug statements...
            if (Parser.Settings.StripDebugStatements && Parser.Settings.IsModificationAllowed(TreeModifications.StripDebugStatements))
            {
                // do it now before we try doing other things
                StripDebugStatements();
            }

            // these variables are used to check for combining a particular type of
            // for-statement with preceding var-statements.
            ForNode targetForNode = null;
            string  targetName    = null;

            // check to see if we want to combine adjacent var statements
            bool combineVarStatements = Parser.Settings.IsModificationAllowed(TreeModifications.CombineVarStatements);

            // check to see if we want to combine a preceding var with a for-statement
            bool moveVarIntoFor = Parser.Settings.IsModificationAllowed(TreeModifications.MoveVarIntoFor);

            // look at the statements in the block.
            // if there are multiple var statements adjacent to each other, combine them.
            // walk BACKWARDS down the list because we'll be removing items when we encounter
            // multiple vars.
            // we also don't need to check the first one, since there is nothing before it.
            for (int ndx = m_list.Count - 1; ndx > 0; --ndx)
            {
                // if the previous node is not a Var, then we don't need to try and combine
                // it withthe current node
                Var previousVar = m_list[ndx - 1] as Var;
                if (previousVar != null)
                {
                    // see if THIS item is also a Var...
                    if (m_list[ndx] is Var && combineVarStatements)
                    {
                        // add the items in this VAR to the end of the previous
                        previousVar.Append(m_list[ndx]);

                        // delete this item from the block
                        m_list.RemoveAt(ndx);

                        // if we have a target for-node waiting for another comparison....
                        if (targetForNode != null)
                        {
                            // check to see if the variable we are looking for is in the new list
                            if (previousVar.Contains(targetName))
                            {
                                // IT DOES! we can combine the var statement with the initializer in the for-statement
                                // we already know it's a binaryop, or it wouldn't be a target for-statement
                                BinaryOperator binaryOp = targetForNode.Initializer as BinaryOperator;

                                // create a vardecl that matches our assignment initializer
                                // ignore duplicates because this scope will already have the variable defined.
                                VariableDeclaration varDecl = new VariableDeclaration(
                                    binaryOp.Context.Clone(),
                                    Parser,
                                    targetName,
                                    binaryOp.Operand1.Context.Clone(),
                                    binaryOp.Operand2,
                                    0,
                                    true
                                    );
                                // append it to the preceding var-statement
                                previousVar.Append(varDecl);

                                // move the previous vardecl to our initializer
                                targetForNode.ReplaceChild(targetForNode.Initializer, previousVar);

                                // and remove the previous var from the list.
                                m_list.RemoveAt(ndx - 1);
                                // this will bump the for node up one position in the list, so the next iteration
                                // will be right back on this node, but the initializer will not be null

                                // but now we no longer need the target mechanism -- the for-statement is
                                // not the current node again
                                targetForNode = null;
                            }
                        }
                    }
                    else if (moveVarIntoFor)
                    {
                        // see if this item is a ForNode
                        ForNode forNode = m_list[ndx] as ForNode;
                        if (forNode != null)
                        {
                            // and see if the forNode's initializer is empty
                            if (forNode.Initializer != null)
                            {
                                // not empty -- see if it is a Var node
                                Var varInitializer = forNode.Initializer as Var;
                                if (varInitializer != null)
                                {
                                    // we want to PREPEND the initializers in the previous var statement
                                    // to our for-statement's initializer list
                                    varInitializer.InsertAt(0, previousVar);

                                    // then remove the previous var statement
                                    m_list.RemoveAt(ndx - 1);
                                    // this will bump the for node up one position in the list, so the next iteration
                                    // will be right back on this node in case there are other var statements we need
                                    // to combine
                                }
                                else
                                {
                                    // see if the initializer is a simple assignment
                                    BinaryOperator binaryOp = forNode.Initializer as BinaryOperator;
                                    if (binaryOp != null && binaryOp.OperatorToken == JSToken.Assign)
                                    {
                                        // it is. See if it's a simple lookup
                                        Lookup lookup = binaryOp.Operand1 as Lookup;
                                        if (lookup != null)
                                        {
                                            // it is. see if that variable is in the previous var statement
                                            if (previousVar.Contains(lookup.Name))
                                            {
                                                // create a vardecl that matches our assignment initializer
                                                // ignore duplicates because this scope will already have the variable defined.
                                                VariableDeclaration varDecl = new VariableDeclaration(
                                                    binaryOp.Context.Clone(),
                                                    Parser,
                                                    lookup.Name,
                                                    lookup.Context.Clone(),
                                                    binaryOp.Operand2,
                                                    0,
                                                    true
                                                    );
                                                // append it to the var statement before us
                                                previousVar.Append(varDecl);

                                                // move the previous vardecl to our initializer
                                                forNode.ReplaceChild(forNode.Initializer, previousVar);

                                                // and remove the previous var from the list.
                                                m_list.RemoveAt(ndx - 1);
                                                // this will bump the for node up one position in the list, so the next iteration
                                                // will be right back on this node, but the initializer will not be null
                                            }
                                            else
                                            {
                                                // it's not in the immediately preceding var-statement, but that doesn't mean it won't be in
                                                // a var-statement immediately preceding that one -- in which case they'll get combined and
                                                // then it WILL be in the immediately preceding var-statement. So hold on to this
                                                // for statement and we'll check after we do a combine.
                                                targetForNode = forNode;
                                                targetName    = lookup.Name;
                                            }
                                        }
                                    }
                                }
                            }
                            else
                            {
                                // if it's empty, then we're free to add the previous var statement
                                // to this for statement's initializer. remove it from it's current
                                // position and add it as the initializer
                                m_list.RemoveAt(ndx - 1);
                                forNode.ReplaceChild(forNode.Initializer, previousVar);
                                // this will bump the for node up one position in the list, so the next iteration
                                // will be right back on this node, but the initializer will not be null
                            }
                        }
                    }
                }
                else
                {
                    // not a var statement. make sure the target for-node is cleared.
                    targetForNode = null;

                    ConditionalCompilationComment previousComment = m_list[ndx - 1] as ConditionalCompilationComment;
                    if (previousComment != null)
                    {
                        ConditionalCompilationComment thisComment = m_list[ndx] as ConditionalCompilationComment;
                        if (thisComment != null)
                        {
                            // two adjacent conditional comments -- combine them into the first.
                            // this will actually make the second block a nested block within the first block,
                            // but they'll be flattened when the comment's block gets recursed.
                            previousComment.Statements.Append(thisComment.Statements);

                            // and remove the second one (which is now a duplicate)
                            m_list.RemoveAt(ndx);
                        }
                    }
                }
            }

            if (m_blockScope != null)
            {
                ScopeStack.Push(m_blockScope);
            }
            try
            {
                // call the base class to recurse
                base.AnalyzeNode();
            }
            finally
            {
                if (m_blockScope != null)
                {
                    ScopeStack.Pop();
                }
            }

            // NOW that we've recursively analyzed all the child nodes in this block, let's see
            // if we can further reduce the statements by checking for a couple good opportunities
            if (Parser.Settings.RemoveUnneededCode)
            {
                // Transform: {var foo=expression;return foo;} to: {return expression;}
                if (m_list.Count == 2 && Parser.Settings.IsModificationAllowed(TreeModifications.VarInitializeReturnToReturnInitializer))
                {
                    Var        varStatement    = m_list[0] as Var;
                    ReturnNode returnStatement = m_list[1] as ReturnNode;

                    // see if we have two statements in our block: a var with a single declaration, and a return
                    if (returnStatement != null && varStatement != null &&
                        varStatement.Count == 1 && varStatement[0].Initializer != null)
                    {
                        // now see if the return is returning a lookup for the same var we are declaring in the
                        // previous statement
                        Lookup lookup = returnStatement.Operand as Lookup;
                        if (lookup != null &&
                            string.Compare(lookup.Name, varStatement[0].Identifier, StringComparison.Ordinal) == 0)
                        {
                            // it's a match!
                            // create a combined context starting with the var and adding in the return
                            Context context = varStatement.Context.Clone();
                            context.UpdateWith(returnStatement.Context);

                            // create a new return statement
                            ReturnNode newReturn = new ReturnNode(context, Parser, varStatement[0].Initializer);

                            // clear out the existing statements
                            m_list.Clear();

                            // and add our new one
                            Append(newReturn);
                        }
                    }
                }

                // we do things differently if these statements are the last in a function
                // because we can assume the implicit return
                bool isFunctionLevel = (Parent is FunctionObject);

                // see if we want to change if-statement that forces a return to a return conditional
                if (Parser.Settings.IsModificationAllowed(TreeModifications.IfElseReturnToReturnConditional))
                {
                    // transform: {...; if(cond1)return;} to {...;cond;}
                    // transform: {...; if(cond1)return exp1;else return exp2;} to {...;return cond1?exp1:exp2;}
                    if (m_list.Count >= 1)
                    {
                        // see if the last statement is an if-statement with a true-block containing only one statement
                        IfNode ifStatement = m_list[m_list.Count - 1] as IfNode;
                        if (ifStatement != null &&
                            ifStatement.TrueBlock != null)
                        {
                            // see if this if-statement is structured such that we can convert it to a
                            // Conditional node that is the operand of a return statement
                            Conditional returnOperand = ifStatement.CanBeReturnOperand(null, isFunctionLevel);
                            if (returnOperand != null)
                            {
                                // it can! change it.
                                ReturnNode returnNode = new ReturnNode(
                                    (Context == null ? null : Context.Clone()),
                                    Parser,
                                    returnOperand);

                                // replace the if-statement with the return statement
                                ReplaceChild(ifStatement, returnNode);
                            }
                        }
                        // else last statement is not an if-statement, or true block is not a single statement
                    }

                    // transform: {...; if(cond1)return exp1;return exp2;} to {...; return cond1?exp1:exp2;}
                    // my cascade! changing the two statements to a return may cause us to run this again if the
                    // third statement up becomes the penultimate and is an if-statement
                    while (m_list.Count > 1)
                    {
                        int lastIndex = m_list.Count - 1;
                        // end in a return statement?
                        ReturnNode finalReturn = m_list[lastIndex] as ReturnNode;
                        if (finalReturn != null)
                        {
                            // it does -- see if the penultimate statement is an if-block
                            IfNode ifNode = m_list[lastIndex - 1] as IfNode;
                            if (ifNode != null)
                            {
                                // if followed by return. See if the if statement can be changed to a
                                // return of a conditional, using the operand of the following return
                                // as the ultimate expression
                                Conditional returnConditional = ifNode.CanBeReturnOperand(finalReturn.Operand, isFunctionLevel);
                                if (returnConditional != null)
                                {
                                    // it can! so create the new return statement.
                                    // the context of this new return statement should start with a clone of
                                    // the if-statement and updated with the return statement
                                    Context context = ifNode.Context.Clone();
                                    context.UpdateWith(finalReturn.Context);

                                    // create the new return node
                                    ReturnNode newReturn = new ReturnNode(
                                        context,
                                        Parser,
                                        returnConditional);

                                    // remove the last node (the old return)
                                    m_list.RemoveAt(lastIndex--);

                                    // and replace the if-statement with the new return
                                    m_list[lastIndex] = newReturn;
                                    newReturn.Parent  = this;

                                    // we collapsed the last two statements, and we KNOW the last one is a
                                    // return -- go back up to the top of the loop to see if we can keep going.
                                    continue;
                                }
                            }
                        }

                        // if we get here, then something went wrong, we didn't collapse the last
                        // two statements, so break out of the loop
                        break;
                    }

                    // now we may have converted the last functional statement
                    // from if(cond)return expr to return cond?expr:void 0, which is four
                    // extra bytes. So let's check to see if the last statement in the function
                    // now fits this pattern, and if so, change it back.
                    // We didn't just NOT change it in the first place because changing it could've
                    // enabled even more changes that would save a lot more space. But apparently
                    // those subsequent changes didn't pan out.
                    if (m_list.Count >= 1)
                    {
                        int        lastIndex  = m_list.Count - 1;
                        ReturnNode returnNode = m_list[lastIndex] as ReturnNode;
                        if (returnNode != null)
                        {
                            Conditional conditional = returnNode.Operand as Conditional;
                            if (conditional != null)
                            {
                                VoidNode falseVoid = conditional.FalseExpression as VoidNode;
                                if (falseVoid != null && falseVoid.Operand is ConstantWrapper)
                                {
                                    // we have the required pattern: "return cond?expr:void 0"
                                    // (well, the object of the void is a constant, at least).
                                    // undo it back to "if(cond)return expr" because that takes fewer bytes.

                                    // by default, the operand of the return operator will be the
                                    // true branch of the conditional
                                    AstNode returnOperand = conditional.TrueExpression;

                                    VoidNode trueVoid = conditional.TrueExpression as VoidNode;
                                    if (trueVoid != null && trueVoid.Operand is ConstantWrapper)
                                    {
                                        // the true branch of the conditional is a void operator acting
                                        // on a constant! So really, there is no operand to the return statement
                                        returnOperand = null;

                                        if (Parser.Settings.IsModificationAllowed(TreeModifications.IfConditionReturnToCondition))
                                        {
                                            // actually, we have return cond?void 0:void 0,
                                            // which would get changed back to function{...;if(cond)return}
                                            // BUT we can just shorten it to function{...;cond}
                                            m_list[lastIndex]            = conditional.Condition;
                                            conditional.Condition.Parent = this;
                                            return;
                                        }
                                    }

                                    IfNode ifNode = new IfNode(
                                        returnNode.Context.Clone(),
                                        Parser,
                                        conditional.Condition,
                                        new ReturnNode(returnNode.Context.Clone(), Parser, returnOperand),
                                        null);
                                    m_list[lastIndex] = ifNode;
                                    ifNode.Parent     = this;
                                }
                            }
                        }
                    }
                }
            }
        }
Esempio n. 24
0
        private bool ParseOther(TemplateStream stream, TokenList tokens, ContextStack context, ScopeStack scope, BraceStack brace)
        {
            switch (stream.Current)
            {
            case '[':
                brace.Push(tokens.Add(new Token(stream.Position, 1, stream.Line, TokenType.OpenBrace, context.Current)), scope.Changed);
                stream.Advance();
                return(true);

            case ']':
                var openBrace = brace.Pop(TokenType.OpenBrace);
                var token     = tokens.Add(new Token(stream.Position, 1, stream.Line, TokenType.CloseBrace, context.Current, null, openBrace.Token));
                if (openBrace.Token != null)
                {
                    openBrace.Token.MatchingToken = token;
                }
                stream.Advance();

                if (openBrace.ScopeChanged)
                {
                    var current = scope.Pop();
                    if (current == Scope.Template)
                    {
                        context.Pop(stream.Position);
                        if (stream.Current == '[')
                        {
                            scope.Push(Scope.Separator);
                        }
                    }
                    else if (current == Scope.True)
                    {
                        context.Pop(stream.Position);
                        if (stream.Current == '[')
                        {
                            scope.Push(Scope.False);
                        }
                    }
                }
                return(true);

            case '{':
                //tokens.Add(new Token(stream.Position - 1, 2, TokenType.OpenBlock, context.Current));
                brace.Push(tokens.Add(new Token(stream.Position, 1, stream.Line, TokenType.OpenCurlyBrace, context.Current)), scope.Changed);
                stream.Advance();
                return(true);

            case '}':
                var openCurlyBrace = brace.Pop(TokenType.OpenCurlyBrace);
                token = tokens.Add(new Token(stream.Position, 1, stream.Line, TokenType.CloseCurlyBrace, context.Current, null, openCurlyBrace.Token));
                if (openCurlyBrace.Token != null)
                {
                    openCurlyBrace.Token.MatchingToken = token;
                }
                //tokens.Add(new Token(stream.Position, 1, TokenType.CloseBlock, context.Current));
                stream.Advance();

                if (openCurlyBrace.ScopeChanged)
                {
                    scope.Pop();
                }
                return(true);

            case '(':
                brace.Push(tokens.Add(new Token(stream.Position, 1, stream.Line, TokenType.OpenFunctionBrace, context.Current)), scope.Changed);
                stream.Advance();
                return(true);

            case ')':
                var openFunctionBrace = brace.Pop(TokenType.OpenFunctionBrace);
                token = tokens.Add(new Token(stream.Position, 1, stream.Line, TokenType.CloseFunctionBrace, context.Current, null, openFunctionBrace.Token));
                if (openFunctionBrace.Token != null)
                {
                    openFunctionBrace.Token.MatchingToken = token;
                }
                stream.Advance();

                if (openFunctionBrace.ScopeChanged)
                {
                    scope.Pop();
                }
                return(true);
            }

            if (scope.Current == Scope.Block)
            {
                return(false);
            }

            var name = stream.PeekWord();

            if (name == null)
            {
                return(false);
            }

            if (keywords.Contains(name))
            {
                tokens.Add(new Token(stream.Position, name.Length, stream.Line, TokenType.Keyword, context.Current));
            }

            stream.Advance(name.Length);
            return(true);
        }