Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/scriptsync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { ScriptLanguage } from "./shared/languageservice";
import { CompilationResult, RuntimeDebug, RuntimeError } from "./viewereditwsclient";
import { normalizePath } from "./interfaces/hostinterface";
import { SynchService } from "./synchservice";
import { IncludeInfo } from "./shared/parser";

//====================================================================
interface TrackedDocuments {
Expand All @@ -48,6 +49,8 @@ export class ScriptSync implements vscode.Disposable {
private lineMappings?: LineMapping[];
private config: ConfigService;

private includedFiles : IncludeInfo[] = [];

//====================================================================
public constructor(
masterDocument: vscode.TextDocument,
Expand Down Expand Up @@ -255,6 +258,12 @@ export class ScriptSync implements vscode.Disposable {
this.addDiagnostics(diagnosticList);
}

public usesInclude(filePath:string) : boolean {
return this.includedFiles.some(
include => include.path === filePath,
);
}

public static preprocessorErrorsToDiagnostics(
errors: PreprocessorError[],
sourceName: string = "Second Life Preprocessor"
Expand Down Expand Up @@ -386,6 +395,10 @@ export class ScriptSync implements vscode.Disposable {
this.addDiagnostics(diagnostics);
}

if(preprocessorResult.includes && preprocessorResult.includes.length > 0) {
this.includedFiles = preprocessorResult.includes;
}

if (preprocessorResult.success) {
finalContent = preprocessorResult.content;
this.lineMappings = preprocessorResult.lineMappings;
Expand Down
10 changes: 7 additions & 3 deletions src/shared/includeprocessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { Lexer, Token } from './lexer';
import { MacroProcessor } from './macroprocessor';
import { ConditionalProcessor } from './conditionalprocessor';
import { DiagnosticCollector, DiagnosticSeverity, ErrorCodes } from './diagnostics';
import { IncludeInfo } from './parser';

/**
* Result of processing an include directive
Expand Down Expand Up @@ -74,16 +75,17 @@ export class IncludeProcessor {
* @returns Result of the include processing
*/
public async processInclude(
filename: string,
include: IncludeInfo,
sourceFile: NormalizedPath,
isRequire: boolean,
state: IncludeState,
_macros: MacroProcessor,
_conditionals: ConditionalProcessor,
diagnostics?: DiagnosticCollector,
line?: number,
column?: number
): Promise<IncludeResult> {
const filename = include.file;
const line = include.line;
const isRequire = include.isRequire;
// Check max include depth
if (state.includeDepth >= state.maxIncludeDepth) {
const error = `Maximum include depth (${state.maxIncludeDepth}) exceeded for file: ${filename}`;
Expand Down Expand Up @@ -144,6 +146,8 @@ export class IncludeProcessor {
};
}

include.path = resolvedPath;

// Check for circular includes
if (state.includeStack.includes(resolvedPath)) {
const error = `Circular include detected for file: ${resolvedPath}`;
Expand Down
4 changes: 3 additions & 1 deletion src/shared/lexingpreprocessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { ScriptLanguage } from "./languageservice";
import { NormalizedPath, HostInterface } from "../interfaces/hostinterface";
import { FullConfigInterface, ConfigKey } from "../interfaces/configinterface";
import { Lexer } from "./lexer";
import { Parser } from "./parser";
import { IncludeInfo, Parser } from "./parser";
import { MacroProcessor } from "./macroprocessor";
import { DiagnosticSeverity } from "./diagnostics";
import { LineMapping } from "./linemapper";
Expand Down Expand Up @@ -53,6 +53,7 @@ export interface PreprocessorResult {
lineMappings?: LineMapping[];
directiveCount?: number;
issues: PreprocessorError[];
includes?: IncludeInfo[];
}
//#endregion

Expand Down Expand Up @@ -207,6 +208,7 @@ export class LexingPreprocessor {
language,
lineMappings: result.mappings,
issues,
includes: result.includes,
};

} catch (error) {
Expand Down
29 changes: 14 additions & 15 deletions src/shared/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ export interface IncludeInfo {
line: number;
column: number;
isRequire: boolean; // true for SLua require(), false for LSL #include
path?: string;
}

/**
Expand Down Expand Up @@ -415,16 +416,17 @@ export class Parser {
const filename = parser.extractStringValue(fileToken.value);

// Record the include for tracking
parser.includes.push({
const include : IncludeInfo = {
file: filename,
line: token.line,
column: token.column,
isRequire: false,
});
};
parser.includes.push(include);

// Process the include if host interface is available
if (parser.host) {
await parser.processIncludeDirective(filename, token.line, false);
await parser.processIncludeDirective(include);
}
}

Expand All @@ -446,12 +448,13 @@ export class Parser {
const fileToken = parser.current();
const filename = parser.extractStringValue(fileToken.value);

parser.includes.push({
const include : IncludeInfo = {
file: filename,
line: token.line,
column: token.column,
isRequire: true,
});
};
parser.includes.push(include);

// Advance past the string token
parser.advance();
Expand All @@ -464,7 +467,7 @@ export class Parser {

// Process the require if host interface is available
if (parser.host) {
await parser.processRequireDirective(filename, token.line);
await parser.processRequireDirective(include);
}
}
}
Expand Down Expand Up @@ -1139,21 +1142,19 @@ export class Parser {
/**
* Process an include directive by reading, parsing, and merging the included file
*/
private async processIncludeDirective(filename: string, lineNumber: number, isRequire: boolean): Promise<void> {
private async processIncludeDirective(include: IncludeInfo): Promise<void> {
if (!this.host || !this.state.includes) {
throw new Error('Cannot process includes without host interface');
}

// Use the include processor to handle the include
const result = await this.state.includes.processInclude(
filename,
include,
this.sourceFile,
isRequire,
this.state.includeState,
this.state.macros,
this.state.conditionals,
this.diagnostics,
lineNumber,
0 // column position
);

Expand Down Expand Up @@ -1254,7 +1255,7 @@ export class Parser {
/**
* Process a require directive by reading, parsing, wrapping, and registering the module
*/
private async processRequireDirective(filename: string, lineNumber: number): Promise<void> {
private async processRequireDirective(include: IncludeInfo): Promise<void> {
if (!this.host || !this.state.includes) {
throw new Error('Cannot process requires without host interface');
}
Expand All @@ -1266,14 +1267,12 @@ export class Parser {

// Use the include processor to read and tokenize the file
const result = await this.state.includes.processInclude(
filename,
include,
this.sourceFile,
true, // isRequire
this.state.includeState,
this.state.macros,
this.state.conditionals,
this.diagnostics,
lineNumber,
0 // column position
);

Expand Down Expand Up @@ -1333,7 +1332,7 @@ export class Parser {
const wrappedTokens = this.wrapModuleInFunction(
requireParser.outputTokens,
resolvedPath,
lineNumber
include.line
);

// Store the wrapped module
Expand Down
23 changes: 21 additions & 2 deletions src/synchservice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,18 @@ export class SynchService implements vscode.Disposable {
return this.activeSyncs.get(path.normalize(masterFilePath));
}

public findSyncByIncludeFilePath(
includePath: string,
): ScriptSync[] {
const syncs : ScriptSync[] = [];
for(const sync of this.activeSyncs.values()) {
if(sync.usesInclude(includePath)) {
syncs.push(sync);
}
}
return syncs;
}

private static async findMasterFile(
scriptName: string,
): Promise<vscode.Uri | null> {
Expand Down Expand Up @@ -615,9 +627,16 @@ export class SynchService implements vscode.Disposable {
});
}

private onSaveTextDocument(document: vscode.TextDocument): void {
private async onSaveTextDocument(document: vscode.TextDocument): Promise<void> {
const filePath = path.normalize(document.fileName);
this.findSyncByMasterFilePath(filePath)?.handleMasterSaved();
const sync = this.findSyncByMasterFilePath(filePath);
if(sync) {
await sync.handleMasterSaved();
} else {
for(const sync of this.findSyncByIncludeFilePath(filePath)) {
await sync.handleMasterSaved();
}
}
}

private onChangeWindowState(windowState: vscode.WindowState): void {
Expand Down
Loading
Loading