Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
NShaderFormatHelper.cs
Go to the documentation of this file.
1 #region Header Licence
2 // ---------------------------------------------------------------------
3 //
4 // Copyright (c) 2009 Alexandre Mutel and Microsoft Corporation.
5 // All rights reserved.
6 //
7 // This code module is part of NShader, a plugin for visual studio
8 // to provide syntax highlighting for shader languages (hlsl, glsl, cg)
9 //
10 // ------------------------------------------------------------------
11 //
12 // This code is licensed under the Microsoft Public License.
13 // See the file License.txt for the license details.
14 // More info on: http://nshader.codeplex.com
15 //
16 // ------------------------------------------------------------------
17 #endregion
18 using System.Collections.Generic;
19 using System.Text;
20 using System.Text.RegularExpressions;
21 using Microsoft.VisualStudio.Package;
22 using Microsoft.VisualStudio.TextManager.Interop;
23 using NShader.Lexer;
24 
25 namespace NShader
26 {
27  /// <summary>
28  /// Alpha version for reformatting. After some test (more particularly with prepropressor directives),
29  /// we definitely need a fully implemented lexical-parser in order to perform a correct reformatting.
30  /// </summary>
31  public class NShaderFormatHelper
32  {
33  static private Regex matchEndOfStatement;
34  private static Regex matchBraceStart;
35  static NShaderFormatHelper()
36  {
37  matchEndOfStatement = new Regex(@";[\s\r\n]*([\}]?)");
38  matchBraceStart = new Regex(@"\{[\s\r\n]*");
39  }
40 
41  public static List<EditSpan> ReformatCode(IVsTextLines pBuffer, TextSpan span, int tabSize)
42  {
43  string filePath = FilePathUtilities.GetFilePath(pBuffer);
44 
45  // Return dynamic scanner based on file extension
46 
47  List<EditSpan> changeList = new List<EditSpan>();
48  int nbLines;
49  pBuffer.GetLineCount(out nbLines);
50  string codeToFormat;
51 
52  int lastLine;
53  int lastLineIndex;
54  pBuffer.GetLastLineIndex(out lastLine, out lastLineIndex);
55  pBuffer.GetLineText(0, 0, lastLine, lastLineIndex, out codeToFormat);
56 
57  NShaderScanner shaderScanner = NShaderScannerFactory.GetShaderScanner(filePath);
58  Scanner lexer = shaderScanner.Lexer;
59  lexer.SetSource(codeToFormat, 0);
60 
61  int spanStart;
62  int spanEnd;
63  pBuffer.GetPositionOfLineIndex(span.iStartLine, span.iStartIndex, out spanStart);
64  pBuffer.GetPositionOfLineIndex(span.iEndLine, span.iEndIndex, out spanEnd);
65 
66  int state = 0;
67  int start, end;
68  ShaderToken token = (ShaderToken) lexer.GetNext(ref state, out start, out end);
69 
70  List<int> brackets = new List<int>();
71  List<int> delimiters = new List<int>();
72  // !EOL and !EOF
73  int level = 0;
74  int startCopy = 0;
75  int levelParenthesis = 0;
76  while (token != ShaderToken.EOF)
77  {
78  switch (token)
79  {
80  case ShaderToken.LEFT_PARENTHESIS:
81  levelParenthesis++;
82  break;
83  case ShaderToken.RIGHT_PARENTHESIS:
84  levelParenthesis--;
85  if ( levelParenthesis < 0 )
86  {
87  levelParenthesis = 0;
88  }
89  break;
90  case ShaderToken.LEFT_BRACKET:
91  level++;
92  if (codeToFormat[start] == '{' && start >= spanStart && end <= spanEnd)
93  {
94  Match match = matchBraceStart.Match(codeToFormat, start);
95 
96 
97  StringBuilder codeFormatted = new StringBuilder();
98  codeFormatted.Append("{\r\n");
99  int levelToIndentNext = level;
100  if (match.Groups.Count == 2)
101  {
102  string matchStr = match.Groups[1].Value;
103  levelToIndentNext--;
104  }
105  for (int i = 0; i < levelToIndentNext; i++)
106  {
107  for (int j = 0; j < tabSize; j++)
108  {
109  codeFormatted.Append(' ');
110  }
111  }
112  if (match.Groups.Count == 2)
113  {
114  codeFormatted.Append("}\r\n");
115  }
116 
117  TextSpan editTextSpan = new TextSpan();
118 
119  pBuffer.GetLineIndexOfPosition(start,
120  out editTextSpan.iStartLine,
121  out editTextSpan.iStartIndex);
122  pBuffer.GetLineIndexOfPosition(startCopy + match.Index + match.Length,
123  out editTextSpan.iEndLine,
124  out editTextSpan.iEndIndex);
125 
126  changeList.Add(new EditSpan(editTextSpan, codeFormatted.ToString()));
127  }
128  break;
129  case ShaderToken.RIGHT_BRACKET:
130  level--;
131  if (level < 0)
132  {
133  level = 0;
134  }
135  brackets.Add(start);
136  break;
137  case ShaderToken.DELIMITER:
138  if (codeToFormat[start] == ';' && start >= spanStart && end <= spanEnd && levelParenthesis == 0)
139  {
140  Match match = matchEndOfStatement.Match(codeToFormat, start);
141 
142  StringBuilder codeFormatted = new StringBuilder();
143  codeFormatted.Append(";\r\n");
144  int levelToIndentNext = level;
145  bool isBracketFound = (match.Groups.Count == 2 && match.Groups[1].Value == "}");
146  if (isBracketFound)
147  {
148  string matchStr = match.Groups[1].Value;
149  levelToIndentNext--;
150  }
151  for (int i = 0; i < levelToIndentNext; i++)
152  {
153  for (int j = 0; j < tabSize; j++)
154  {
155  codeFormatted.Append(' ');
156  }
157  }
158  if (isBracketFound)
159  {
160  codeFormatted.Append("}\r\n");
161  }
162 
163  TextSpan editTextSpan = new TextSpan();
164 
165  pBuffer.GetLineIndexOfPosition(start,
166  out editTextSpan.iStartLine,
167  out editTextSpan.iStartIndex);
168  pBuffer.GetLineIndexOfPosition(startCopy + match.Index + match.Length,
169  out editTextSpan.iEndLine,
170  out editTextSpan.iEndIndex);
171 
172  changeList.Add(new EditSpan(editTextSpan, codeFormatted.ToString()));
173  }
174  break;
175  }
176  token = (ShaderToken) lexer.GetNext(ref state, out start, out end);
177  }
178  return changeList;
179  }
180  }
181 }
static List< EditSpan > ReformatCode(IVsTextLines pBuffer, TextSpan span, int tabSize)
int GetNext(ref int state, out int start, out int end)
Alpha version for reformatting. After some test (more particularly with prepropressor directives)...