using System;
using System.Diagnostics;
using AnticipatingMinds.Genesis.KnowledgeManagement;
using AnticipatingMinds.Genesis.CodeDOM;
using AnticipatingMinds.Genesis.CodeDOM.Utilities;
using AnticipatingMinds.Genesis.CodeParser;
using System.Threading;
using System.Collections;
using AnticipatingMinds.Genesis;
using AnticipatingMinds.PlatformServices.ErrorReporting;
namespace AnticipatingMinds.Genesis.CodeAnalyzer{
/// <summary>
/// Analysis started event handler.
/// </summary>
public delegate void AnalyzeStartedEventHandler(object sender , EventArgs e);
/// <summary>
/// Analysis ended event handler
/// </summary>
public delegate void AnalyzeEndedEventHandler(object sender , EventArgs e);
/// <summary>
/// Represents analysis progress events class.
/// </summary>
public class AnalyzeProgressEventArgs : EventArgs
{
/// <summary>
/// Initializes new instance of <see cref="AnalyzeProgressEventArgs"/> class.
/// </summary>
/// <param name="percentCompleted">Percent competed.</param>
public AnalyzeProgressEventArgs(int percentCompleted)
{
this.percentComplete = percentCompleted;
}
public int PercentComplete
{
get
{
return percentComplete;
}
}
private int percentComplete = 0;
}
public delegate void AnalyzeProgressEventHandler(object sender , AnalyzeProgressEventArgs e);
public class FileAnalysisEventArgs : EventArgs
{
public FileAnalysisEventArgs(string fileName)
{
this.fileName = fileName;
}
public string FileName
{
get
{
return fileName;
}
}
private string fileName;
}
/// <summary>
/// Raised when new file is about to be analyzed.
/// </summary>
public delegate void FileAnalysisStartedEventHandler(object sender , FileAnalysisEventArgs e);
/// <summary>
/// Raised after file nas been analyzed.
/// </summary>
public delegate void FileAnalysisEndedEventHandler(object sender , FileAnalysisEventArgs e);
public delegate void FileParsingStartedEventHandler(object sender , FileAnalysisEventArgs e);
public delegate void FileParsingEndedEventHandler(object sender , FileAnalysisEventArgs e);
public class RuleViolationFoundEventArgs : EventArgs
{
public RuleViolationFoundEventArgs(RuleViolation violation)
{
this.violation = violation;
}
// RuleViolation object that is the event argument
public RuleViolation Violation
{
get
{
return violation;
}
}
private RuleViolation violation;
}
public delegate void RuleViolationFoundEventHandler(object sender , RuleViolationFoundEventArgs e);
/// <summary>
/// Analyzer acts as the main interface for the UI.
/// </summary>
[System.Security.Permissions.StrongNameIdentityPermissionAttribute(System.Security.Permissions.SecurityAction.LinkDemand,
PublicKey=
"00240000048000009400000006020000002400005253413100040000010001009D309779C258129573FC313836474C75C4CE9F4" +
"107524FA0B9A6DB2E52754459C5A8946E4CBD5B98ACDB2413C5AFD38C1DF00C9A946713E867237B47F9D9CC473D4A853EACBEAB" +
"799EC0A271B468D4B6D52301A414A7772F05FEBD2BA7D0A2835F0D45E401C3C37F9E7B991D29F07DA88E20BB3839A34A2739AB6" +
"56B5204C8BC")]
public class Analyzer
{
public Analyzer(KnowledgeBase knowledgeBase)
{
this.knowledgeBase = knowledgeBase;
}
public event AnalyzeStartedEventHandler AnalyzeStarted;
public event AnalyzeProgressEventHandler AnalyzeProgress;
public event AnalyzeEndedEventHandler AnalyzeEnded;
public event FileAnalysisStartedEventHandler FileAnalysisStarted;
public event FileAnalysisEndedEventHandler FileAnalysisEnded;
public event RuleViolationFoundEventHandler RuleViolationFound;
#region Event handlers for Analyzer events
protected void OnAnalyzeStarted()
{
if(AnalyzeStarted != null)
{
AnalyzeStarted(this , EventArgs.Empty);
}
}
protected void OnAnalyzeEnded()
{
if(AnalyzeEnded != null)
{
AnalyzeEnded(this , EventArgs.Empty);
}
}
protected void OnAnalyzeProgressed(int percentCompleted)
{
if(AnalyzeProgress != null)
AnalyzeProgress(this,new AnalyzeProgressEventArgs(percentCompleted));
}
protected void OnFileAnalysisStarted(string fileName)
{
if(FileAnalysisStarted != null)
FileAnalysisStarted(this,new FileAnalysisEventArgs(fileName));
}
protected void OnFileAnalysisEnded(string fileName)
{
if(FileAnalysisEnded != null)
FileAnalysisEnded(this,new FileAnalysisEventArgs(fileName));
}
protected void OnRuleViolationFound(RuleViolation violation)
{
if(RuleViolationFound != null)
RuleViolationFound(this,new RuleViolationFoundEventArgs(violation));
}
#endregion
#region Private Methods
private CodeDomWalker.WalkerCallbackReturn CodeElementAnalyzer(CodeElement element,CodeDomWalker.CallBackNotificationType notificationType, CodeDomWalkerContext walkerContext,object applicationData)
{
switch(notificationType)
{
case CodeDomWalker.CallBackNotificationType.OnElement:
{
if(cancelRequestedEvent.WaitOne(0,false))
return CodeDomWalker.WalkerCallbackReturn.Cancel;
codeElementsToAnalyzedSoFar++;
if((float)((float)codeElementsToAnalyzedSoFar/(float)totalCodeElementsToAnalyze)*100.0 != this.lastReportedProgress)
{
lastReportedProgress = (int) ((float)((float)codeElementsToAnalyzedSoFar/(float)totalCodeElementsToAnalyze)*100.0);
OnAnalyzeProgressed(lastReportedProgress);
}
//Get rules for this code element
RuleCollection rulesForType = new RuleCollection();
Type elementType = element.GetType();
while(elementType != null && elementType != typeof(System.Object))
{
RuleCollection registeredRulesForType = rulesCategorizedByType[elementType] as RuleCollection;
if(registeredRulesForType != null)
foreach(Rule rule in registeredRulesForType)
if(!rulesForType.Contains(rule) && !rulesThrownException.Contains(rule))
rulesForType.Add(rule);
elementType = elementType.BaseType;
}
if(rulesForType.Count == 0)
return CodeDomWalker.WalkerCallbackReturn.Next;
foreach(Rule rule in rulesForType)
{
RuleViolation[] violations = null;
try
{
violations = rule.Analyze(element,this.cancelRequestedEvent);
}
catch(Exception e)
{
rulesThrownException.Add(rule);
ExceptionsManager.ReportUnhandledException(e,"DevAdvantage");
}
if(violations != null)
foreach(RuleViolation violation in violations)
OnRuleViolationFound(violation);
}
break;
}
}
return CodeDomWalker.WalkerCallbackReturn.Next;
}
private CodeDomWalker.WalkerCallbackReturn CodeElementCounter(CodeElement element,CodeDomWalker.CallBackNotificationType notificationType, CodeDomWalkerContext walkerContext,object applicationData)
{
switch(notificationType)
{
case CodeDomWalker.CallBackNotificationType.OnElement:
{
totalCodeElementsToAnalyze++;
break;
}
}
return CodeDomWalker.WalkerCallbackReturn.Next;
}
private RuleCollection GetProfileRules(Profile profile,bool includeNestedProfile)
{
RuleCollection rules = new RuleCollection();
foreach(string ruleId in profile.Rules)
{
try
{
Rule ruleToAdd = knowledgeBase.GetRuleById(ruleId);
if(ruleToAdd != null && !rules.Contains(ruleToAdd))
rules.Add(ruleToAdd);
}
//Ignore KB exceptions (like rule template is unavailable)
catch(KnowledgeBaseException)
{
}
}
if(includeNestedProfile)
{
foreach(string nestedProfileId in knowledgeBase.GetProfileChildrenIds(profile.Id))
{
try
{
Profile child = knowledgeBase.GetProfileById(nestedProfileId);
foreach(string ruleId in child.Rules)
{
Rule ruleToAdd = knowledgeBase.GetRuleById(ruleId);
if(ruleToAdd!= null && !rules.Contains(ruleToAdd))
rules.Add(ruleToAdd);
}
}
//Ignore KB exceptions (like rule template is unavailable)
catch(KnowledgeBaseException)
{
}
}
}
return rules;
}
#endregion
#region Public Instance Methods (Analyze)
/// <summary>
/// Perform analysis of requested items.
/// </summary>
/// <param name="profilesToAnalyze">A collection of profiles that are used in analysis</param>
/// <param name="request">Specifies what items has to be analyzed.</param>
/// <param name="cancelRequestedEvent">Event that when set indicates that user requested cancelation of current operation.</param>
public void Analyze(ProfileCollection profilesToAnalyze , AnalysisRequest request, ManualResetEvent cancelRequestedEvent)
{
RuleCollection ruleCollection = new RuleCollection();
foreach(Profile profile in profilesToAnalyze)
foreach(Rule rule in GetProfileRules(profile,true))
{
try
{
// Handles case where ruleId associated with a
// profile no longer exists in the KB. JLR 7/20/03
if(rule != null && !ruleCollection.Contains(rule))
ruleCollection.Add(rule);
}
//Ignore KB exceptions (like rule template is unavailable)
catch(KnowledgeBaseException)
{
}
}
Analyze(ruleCollection,request,cancelRequestedEvent);
}
public void Analyze(Profile profileToAnalyze , AnalysisRequest request,ManualResetEvent cancelRequestedEvent)
{
ProfileCollection profileCollection = new ProfileCollection();
profileCollection.Add(profileToAnalyze);
Analyze(profileCollection , request , cancelRequestedEvent);
}
private int totalCodeElementsToAnalyze = 0;
private int codeElementsToAnalyzedSoFar = 0;
private int lastReportedProgress = 0;
private ManualResetEvent cancelRequestedEvent;
private Hashtable rulesCategorizedByType = null;
private RuleCollection rulesThrownException = new RuleCollection();
public void Analyze(RuleCollection rulesToAnalyze , AnalysisRequest analysisRequest,ManualResetEvent cancelRequestedEvent)
{
totalCodeElementsToAnalyze = 0;
codeElementsToAnalyzedSoFar = 0;
lastReportedProgress = 0;
this.cancelRequestedEvent = cancelRequestedEvent;
// Raise the event that indicates analysis has begun
OnAnalyzeStarted();
//categorize rules by targeted elements
#region Rule Categorization
rulesCategorizedByType = new Hashtable(rulesToAnalyze.Count);
rulesThrownException.Clear();
RuleCollection uniqueRulesToAnalyze = new RuleCollection();
foreach(Rule rule in rulesToAnalyze)
{
if(!uniqueRulesToAnalyze.Contains(rule))
uniqueRulesToAnalyze.Add(rule);
}
foreach(Rule rule in uniqueRulesToAnalyze)
{
if(rule.IsDisabled)
continue;
if(rule.TargetedCodeElements == null)
continue;
foreach(Type codeElementToWatch in rule.TargetedCodeElements)
{
if(codeElementToWatch == null)
{
continue;
}
RuleCollection rulesForType = (RuleCollection) rulesCategorizedByType[codeElementToWatch];
if(rulesForType == null)
{
rulesForType = new RuleCollection();
rulesCategorizedByType[codeElementToWatch] = rulesForType;
}
if(!rulesForType.Contains(rule))
rulesForType.Add(rule);
//Are we canceled
if(cancelRequestedEvent.WaitOne(0,false))
{
OnAnalyzeEnded();
return;
}
}
}
#endregion Rule Categorization
//Update total number of elements to analyze
foreach(CodeAssemblyFile item in analysisRequest.ItemsToAnalyze)
{
if(!(item is CodeCompileUnit))
continue;
CodeCompileUnit unit = item as CodeCompileUnit;
if(unit != null)
CodeDomWalker.WalkCompileUnit(unit,new CodeDomWalker.WalkerCallback(CodeElementCounter));
}
//And finally - analyze code dom!
foreach(CodeAssemblyFile assemblyFile in analysisRequest.ItemsToAnalyze)
{
OnFileAnalysisStarted(assemblyFile.SourceFileName);
CodeDomWalker.WalkCompileUnit(assemblyFile,new CodeDomWalker.WalkerCallback(CodeElementAnalyzer));
OnFileAnalysisEnded(assemblyFile.SourceFileName);
}
// Raise the event that indicates the analysis has ended
// (complete or cancelled).
OnAnalyzeEnded();
}
#endregion
#region Private Instance variables
private KnowledgeBase knowledgeBase = null;
#endregion
}
}
|