// NAnt - A .NET build tool
// Copyright (C) 2001-2004 Gerry Shaw
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Matthew Mastracci (matt@aclaro.com)
// Scott Ford (sford@RJKTECH.com)
// Gert Driesen (gert.driesen@ardatis.com)
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Specialized;
using System.Globalization;
using System.IO;
using System.Xml;
using NAnt.Core;
using NAnt.Core.Util;
namespace NAnt.VSNet {
public abstract class ProjectReferenceBase : ReferenceBase {
#region Protected Instance Constructors
protected ProjectReferenceBase(ReferencesResolver referencesResolver, ProjectBase parent) : base(referencesResolver, parent) {
}
#endregion Protected Instance Constructors
#region Protected Instance Properties
protected abstract bool IsPrivate {
get;
}
protected abstract bool IsPrivateSpecified {
get;
}
#endregion Protected Instance Properties
#region Override implementation of ReferenceBase
///
/// Gets a value indicating whether the output file(s) of this reference
/// should be copied locally.
///
///
/// if the output file(s) of this reference
/// should be copied locally; otherwise, .
///
public override bool CopyLocal {
get { return IsPrivateSpecified ? IsPrivate : true; }
}
public override string Name {
get { return Project.Name; }
}
///
/// Gets a value indicating whether this reference represents a system
/// assembly.
///
///
/// as a project by itself can never be a
/// system assembly.
///
protected override bool IsSystem {
get { return false; }
}
///
/// Gets the output path of the reference, without taking the "copy local"
/// setting into consideration.
///
/// The solution configuration that is built.
///
/// The output path of the reference.
///
public override string GetPrimaryOutputFile(string solutionConfiguration) {
return Project.GetOutputPath(solutionConfiguration);
}
///
/// Gets the complete set of output files for the referenced project.
///
/// The solution configuration that is built.
/// The set of output files to be updated.
///
/// The complete set of output files for the referenced project.
///
///
/// The key of the case-insensitive is the
/// full path of the output file and the value is the path relative to
/// the output directory.
///
public override void GetOutputFiles(string solutionConfiguration, Hashtable outputFiles) {
Project.GetOutputFiles(solutionConfiguration, outputFiles);
}
///
/// Gets the complete set of assemblies that need to be referenced when
/// a project references this project.
///
/// The solution configuration that is built.
///
/// The complete set of assemblies that need to be referenced when a
/// project references this project.
///
///
///
/// Apparently, there's some hack in VB.NET that allows a type to be used
/// that derives from a type in an assembly that is not referenced by the
/// project.
///
///
/// When building from the command line (using vbc), the following error
/// is reported "error BC30007: Reference required to assembly 'X'
/// containing the base class 'X'. Add one to your project".
///
///
/// Somehow VB.NET can workaround this issue, without actually adding a
/// reference to that assembly. I verified this with both VS.NET 2003 and
/// VS.NET 2005.
///
///
/// For now, we have no other option than to return all assembly
/// references of the referenced project if the parent is a VB.NET
/// project.
///
///
public override StringCollection GetAssemblyReferences(string solutionConfiguration) {
StringCollection assemblyReferences = null;
// check if parent is a VB.NET project
if (typeof(VBProject).IsAssignableFrom(Parent.GetType())) {
assemblyReferences = Project.GetAssemblyReferences(solutionConfiguration);
} else {
assemblyReferences = new StringCollection();
}
string projectOutputFile = Project.GetConfiguration(
solutionConfiguration).BuildPath;
// check if project has output file
if (projectOutputFile != null) {
if (File.Exists(projectOutputFile)) {
// add primary output to list of reference assemblies
assemblyReferences.Add(projectOutputFile);
}
}
// return assembly references
return assemblyReferences;
}
///
/// Gets the timestamp of the reference.
///
/// The solution configuration that is built.
///
/// The timestamp of the reference.
///
public override DateTime GetTimestamp(string solutionConfiguration) {
string projectOutputFile = Project.GetOutputPath(solutionConfiguration);
if (projectOutputFile != null) {
return GetFileTimestamp(projectOutputFile);
} else {
// if project has no output file, then we assume that it creates
// a file through another way (eg. by launching an application
// that creates an assembly)
return DateTime.MaxValue;
}
}
#endregion Override implementation of ReferenceBase
#region Public Instance Properties
public abstract ProjectBase Project {
get;
}
#endregion Public Instance Properties
#region Protected Instance Methods
protected ProjectBase LoadProject(SolutionBase solution, TempFileCollection tfc, GacCache gacCache, DirectoryInfo outputDir, string projectFile) {
if (ProjectStack.Contains(projectFile)) {
throw new BuildException(string.Format(CultureInfo.InvariantCulture,
"Circular reference to \"{0}\" detected in project \"{1}\".",
Path.GetFileNameWithoutExtension(projectFile), Parent.Name),
Location.UnknownLocation);
}
try {
ProjectStack.Push(projectFile);
Log(Level.Verbose, "Loading referenced project '{0}'.", projectFile);
return ProjectFactory.LoadProject(solution, SolutionTask, tfc,
gacCache, ReferencesResolver, outputDir, projectFile);
} finally {
ProjectStack.Pop();
}
}
#endregion Protected Instance Methods
#region Private Static Fields
private static readonly Stack ProjectStack = new Stack();
#endregion Private Static Fields
}
}