Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const ICON_TYPES = {
DART: `${ICON_PATH}dart.svg`,
SQL: `${ICON_PATH}sql.svg`,
GO: `${ICON_PATH}go.svg`,
SCALA: `${ICON_PATH}scala.svg`,
C: `${ICON_PATH}c.svg`,
};

Expand Down Expand Up @@ -47,6 +48,8 @@ function CodeNode({ node, renderType }) {
iconUrl = ICON_TYPES.SQL;
} else if (node.assetType === 'go') {
iconUrl = ICON_TYPES.GO;
} else if (node.assetType === 'scala') {
iconUrl = ICON_TYPES.SCALA;
} else if (node.assetType === 'c') {
iconUrl = ICON_TYPES.C;
} else if (node.assetType === 'dart') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const ICON_TYPES = {
DART: `${ICON_PATH}dart.svg`,
SQL: `${ICON_PATH}sql.svg`,
GO: `${ICON_PATH}go.svg`,
SCALA: `${ICON_PATH}scala.svg`,
C: `${ICON_PATH}c.svg`,
};

Expand Down Expand Up @@ -55,6 +56,8 @@ function getIcon(node) {
iconUrl = ICON_TYPES.SQL;
} else if (node.value === 'go') {
iconUrl = ICON_TYPES.GO;
} else if (node.value === 'scala') {
iconUrl = ICON_TYPES.SCALA;
} else if (node.value === 'c') {
iconUrl = ICON_TYPES.C;
} else if (node.value === 'dart') {
Expand Down
5 changes: 5 additions & 0 deletions app/constants/assets-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ module.exports = {
extensions: ['rs'],
categories: ['code'],
},
{
name : 'Scala',
extensions: ['scala'],
categories: ['code'],
},
{
name: 'Dart',
extensions: ['dart'],
Expand Down
1 change: 1 addition & 0 deletions app/images/scala.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions app/preload.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import ProjectUtil from './utils/project';
import JavaHandler from './services/assets/handlers/java';
import RustHandler from './services/assets/handlers/rust';
import GoHandler from './services/assets/handlers/go';
import ScalaHandler from './services/assets/handlers/scala';
import CppHandler from './services/assets/handlers/cpp';
import CHandler from './services/assets/handlers/c';
import Constants from './constants/constants';
Expand Down Expand Up @@ -63,6 +64,7 @@ contextBridge.exposeInMainWorld('workerElectronBridge', {
new RustHandler(),
new SQLHandler(),
new GoHandler(),
new ScalaHandler(),
new CppHandler(),
new CHandler(),
new DartHandler(),
Expand Down
267 changes: 267 additions & 0 deletions app/services/assets/handlers/scala.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
import BaseCodeHandler from './baseCode';
import Constants from '../../../constants/constants';

const FILE_EXTENSION_LIST = ['scala'];

export default class ScalaHandler extends BaseCodeHandler {
static id = 'StatWrap.ScalaHandler';

constructor() {
super(ScalaHandler.id, FILE_EXTENSION_LIST);
}

id() {
return ScalaHandler.id;
}

getLibraryId(packageName, importName) {
let id = '';
if (packageName && importName) {
id = `${packageName}.${importName}`;
} else if (packageName) {
id = packageName;
} else if (importName) {
id = importName;
} else {
id = '(unknown)';
}
return id;
}

getInputs(uri, text) {
const inputs = [];
if (!text || text.trim() === '') {
return inputs;
}

// For file read operations
const processedPaths = new Set();

// For nested reader operations like BufferedReader, InputStreamReader
const nestedReaderMatches = [
...text.matchAll(/new\s+(BufferedReader|InputStreamReader)\s*\(\s*new\s+(?:FileReader|FileInputStream)\s*\(\s*(?:new\s+File\s*\(\s*)?(['"]{1,}[\s\S]*?['"]{1,}|[a-zA-Z0-9_.]+)[\s\S]*?\)\s*\)/gim),
];

for (let index = 0; index < nestedReaderMatches.length; index++) {
const match = nestedReaderMatches[index];
const operation = match[1];
const path = match[2].trim();
if (!processedPaths.has(path)) {
inputs.push({
id: `${operation} - ${path}`,
type: Constants.DependencyType.DATA,
path,
});
processedPaths.add(path);
}
}

// For direct file read operations
const fileReadMatches = [
...text.matchAll(/new\s+(FileInputStream|FileReader|Scanner)\s*\(\s*(?:new\s+File\s*\(\s*)?(['"]{1,}[\s\S]*?['"]{1,}|[a-zA-Z0-9_.]+)[\s\S]*?\)/gim),
...text.matchAll(/Files\.(?:(read|readAllLines|readAllBytes|newBufferedReader|newInputStream))\s*\(\s*(?:Paths\.get\s*\(\s*)?\s*(['"]{1,}[\s\S]*?['"]{1,}|[a-zA-Z0-9_.]+)[\s\S]*?\)/gim),
...text.matchAll(/((?:scala\.io\.)?Source\.fromFile)\s*\(\s*(?:new\s+File\s*\(\s*)?(['"]{1,}[\s\S]*?['"]{1,}|[a-zA-Z0-9_.]+)[\s\S]*?\)/gim),
];

for (let index = 0; index < fileReadMatches.length; index++) {
const match = fileReadMatches[index];
const operation = match[1] || 'Files.read';
const path = match.length > 2 ? match[2].trim() : match[1].trim();

if (!processedPaths.has(path)) {
inputs.push({
id: `${operation} - ${path}`,
type: Constants.DependencyType.DATA,
path,
});
processedPaths.add(path);
}
}

// For Spark Big Data IO operations
const sparkReadMatches = [
...text.matchAll(/\b(csv|parquet|json|text|textFile|orc|jdbc|load)\s*\(\s*(['"]{1,}[\s\S]*?['"]{1,}|[a-zA-Z0-9_.]+)[\s\S]*?\)/gim),
];

for (let index = 0; index < sparkReadMatches.length; index++) {
const match = sparkReadMatches[index];
const operation = match[1].trim();
const path = match[2].trim();

if (!processedPaths.has(path)) {
inputs.push({
id: `${operation} - ${path}`,
type: Constants.DependencyType.DATA,
path,
});
processedPaths.add(path);
}
}

// For database operations
const jdbcMatches = [
...text.matchAll(/DriverManager\.getConnection\s*\(\s*(['"]{1,}\s*?[\s\S]+?['"]{1,})[\s\S]*?\)/gim),
];

for (let index = 0; index < jdbcMatches.length; index++) {
const match = jdbcMatches[index];
const path = match[1].trim();
inputs.push({
id: `JDBC - ${path}`,
type: Constants.DependencyType.DATA,
path,
});
}

return inputs;
}

getOutputs(uri, text) {
const outputs = [];
if (!text || text.trim() === '') {
return outputs;
}

// For file write operations
const processedPaths = new Set();

// For nested writer operations like BufferedWriter, OutputStreamWriter
const nestedWriterMatches = [
...text.matchAll(/new\s+(BufferedWriter|OutputStreamWriter)\s*\(\s*new\s+(?:FileWriter|FileOutputStream)\s*\(\s*(?:new\s+File\s*\(\s*)?(['"]{1,}\s*?[\s\S]+?['"]{1,})[\s\S]*?\)\s*\)/gim),
];

for (let index = 0; index < nestedWriterMatches.length; index++) {
const match = nestedWriterMatches[index];
const operation = match[1];
const path = match[2].trim();
if (!processedPaths.has(path)) {
outputs.push({
id: `${operation} - ${path}`,
type: Constants.DependencyType.DATA,
path,
});
processedPaths.add(path);
}
}

// For file write operations
const fileWriteMatches = [
...text.matchAll(/new\s+(FileOutputStream|FileWriter|PrintWriter)\s*\(\s*(?:new\s+File\s*\(\s*)?(['"]{1,}[\s\S]*?['"]{1,}|[a-zA-Z0-9_.]+)[\s\S]*?\)/gim),
...text.matchAll(/Files\.(?:write|writeString|newBufferedWriter|newOutputStream)\s*\(\s*(?:Paths\.get\s*\(\s*)?\s*(['"]{1,}[\s\S]*?['"]{1,}|[a-zA-Z0-9_.]+)[\s\S]*?\)/gim),
];

for (let index = 0; index < fileWriteMatches.length; index++) {
const match = fileWriteMatches[index];
const operation = match[1] || 'Files.write';
const path = match.length > 2 ? match[2].trim() : match[1].trim();

if (!processedPaths.has(path)) {
outputs.push({
id: `${operation} - ${path}`,
type: Constants.DependencyType.DATA,
path,
});
processedPaths.add(path);
}
}

// For spark / big data write operations
const sparkWriteMatches = [
...text.matchAll(/\b(csv|parquet|json|text|textFile|orc|jdbc|save|saveAsTable|saveAsTextFile)\s*\(\s*(['"]{1,}[\s\S]*?['"]{1,}|[a-zA-Z0-9_.]+)[\s\S]*?\)/gim),
];

for (let index = 0; index < sparkWriteMatches.length; index++) {
const match = sparkWriteMatches[index];
const operation = match[1].trim();
const path = match[2].trim();

if (!processedPaths.has(path)) {
outputs.push({
id: `${operation} - ${path}`,
type: Constants.DependencyType.DATA,
path,
});
processedPaths.add(path);
}
}

// For image write operations
const imageWriteMatches = [
...text.matchAll(/ImageIO\.write\s*\(\s*[\s\S]*?,\s*['"]{1,}[\s\S]+?['"]{1,}\s*,\s*(?:new\s+File\s*\(\s*)?(['"]{1,}\s*?[\s\S]+?['"]{1,})[\s\S]*?\)/gim),
];

for (let index = 0; index < imageWriteMatches.length; index++) {
const match = imageWriteMatches[index];
const path = match[1].trim();
outputs.push({
id: `ImageIO.write - ${path}`,
type: Constants.DependencyType.FIGURE,
path,
});
}

// For chart export operations
const chartExportMatches = [
...text.matchAll(/ChartUtilities\.saveChartAs(?:JPEG|PNG)\s*\(\s*(?:new\s+File\s*\(\s*)?(['"]{1,}[\s\S]+?['"]{1,})[\s\S]*?\)/gim),
...text.matchAll(/ChartUtils\.saveChartAs(?:JPEG|PNG)\s*\(\s*(?:new\s+File\s*\(\s*)?(['"]{1,}[\s\S]+?['"]{1,})[\s\S]*?\)/gim),
];

for (let index = 0; index < chartExportMatches.length; index++) {
const match = chartExportMatches[index];
const path = match[1].trim();
outputs.push({
id: `Chart Export - ${path}`,
type: Constants.DependencyType.FIGURE,
path,
});
}

return outputs;
}

getLibraries(uri, text) {
const libraries = [];
if (!text || text.trim() === '') {
return libraries;
}

const packageMatches = [
...text.matchAll(/package\s+([\w.]+)/gm),
];

let currentPackage = '';
if (packageMatches.length > 0) {
currentPackage = packageMatches[0][1];
}

const importMatches = [
...text.matchAll(/import\s+(?:static\s+)?([^;\r\n]+)/gm),
];

for (let index = 0; index < importMatches.length; index++) {
const match = importMatches[index];
const fullImport = match[1].trim();

let packageName, className;
const lastDotIndex = fullImport.lastIndexOf('.');

if (lastDotIndex !== -1) {
packageName = fullImport.substring(0, lastDotIndex);
className = fullImport.substring(lastDotIndex + 1);
} else {
packageName = fullImport;
className = '*';
}


libraries.push({
id: this.getLibraryId(packageName, className),
module: packageName,
import: className,
alias: null,
});
}

return libraries;
}
}
5 changes: 5 additions & 0 deletions app/utils/workflow.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import JavaHandler from '../services/assets/handlers/java';
import RustHandler from '../services/assets/handlers/rust';
import SQLHandler from '../services/assets/handlers/sql';
import GoHandler from '../services/assets/handlers/go';
import ScalaHandler from '../services/assets/handlers/scala';
import CppHandler from '../services/assets/handlers/cpp';
import CHandler from '../services/assets/handlers/c';
import DartHandler from '../services/assets/handlers/dart';
Expand Down Expand Up @@ -66,6 +67,8 @@ export default class WorkflowUtil {
assetType = 'sql';
} else if (AssetUtil.getHandlerMetadata(GoHandler.id, asset.metadata)) {
assetType = 'go';
} else if (AssetUtil.getHandlerMetadata(ScalaHandler.id, asset.metadata)) {
assetType = 'scala';
} else if (AssetUtil.getHandlerMetadata(CHandler.id, asset.metadata)) {
assetType = 'c';
} else if (AssetUtil.getHandlerMetadata(DartHandler.id, asset.metadata)) {
Expand Down Expand Up @@ -371,6 +374,7 @@ export default class WorkflowUtil {
WorkflowUtil._getMetadataDependencies(asset, RustHandler.id, libraries, inputs, outputs);
WorkflowUtil._getMetadataDependencies(asset, SQLHandler.id, libraries, inputs, outputs);
WorkflowUtil._getMetadataDependencies(asset, GoHandler.id, libraries, inputs, outputs);
WorkflowUtil._getMetadataDependencies(asset, ScalaHandler.id, libraries, inputs, outputs);
WorkflowUtil._getMetadataDependencies(asset, CppHandler.id, libraries, inputs, outputs);
WorkflowUtil._getMetadataDependencies(asset, CHandler.id, libraries, inputs, outputs);

Expand Down Expand Up @@ -440,6 +444,7 @@ export default class WorkflowUtil {
WorkflowUtil._getMetadataDependencies(asset, RustHandler.id, libraries, [], []);
WorkflowUtil._getMetadataDependencies(asset, SQLHandler.id, libraries, [], []);
WorkflowUtil._getMetadataDependencies(asset, GoHandler.id, libraries, [], []);
WorkflowUtil._getMetadataDependencies(asset, ScalaHandler.id, libraries, [], []);
WorkflowUtil._getMetadataDependencies(asset, CppHandler.id, libraries, [], []);
WorkflowUtil._getMetadataDependencies(asset, CHandler.id, libraries, [], []);
WorkflowUtil._getMetadataDependencies(asset, DartHandler.id, libraries, [], []);
Expand Down
Loading